一个 msvc 与 gcc/clang 不一致的例子,哪边是对的?

2020-11-25 14:16:58 +08:00
 wutiantong

下面的代码基于 C++17,msvc 是最新版本的( 16.8.2 ),gcc/clang 也是最新版本的,可在线运行:godblot

namespace user
{
    template<typename T> const T unit { 1 };

    template<typename Def>
    struct data
    {
        typename Def::value_type val;
    };
    template<typename Def> const data<Def> unit<data<Def>> { Def::unit_val() };

    struct decimal_def
    {
        using  value_type = int;
        static value_type unit_val() noexcept { return 10; }
    };
    using decimal_data = data<decimal_def>;
    inline const auto decimal_data_unit = unit<decimal_data>;
}

#include <iostream>
int main()
{
    std::cout << user::decimal_data_unit.val << std::endl;
}

预期输出:10

msvc 输出:0

gcc/clang 输出:10

2466 次点击
所在节点    C++
5 条回复
wutiantong
2020-11-25 15:10:13 +08:00
顺带提一下,这样修改可以使 msvc 的输出符合预期:

inline const auto & decimal_data_unit = unit<decimal_data>;

主要想讨论一下,上面的写法是否有问题,还是编译器的 bug ?
lcdtyph
2020-11-25 16:14:11 +08:00
static constexpr value_type unit_val() noexcept { return 10; }
wutiantong
2020-11-25 16:50:29 +08:00
@lcdtyph 确实是 work 的,而且我发现问题还跟 data 的构造函数有关:

如果给 data 上一个普通的构造函数,结果又不行了(变成 0 ),需要再进一步把构造函数修饰成 constexpr (这也说明例子中原本默认的 aggregate 构造函数是 constexpr,但我好像没找到标准说明?)

所以问题是,这个行为到底是 msvc 比较正确还是 gcc 比较正确呢?
lcdtyph
2020-11-25 17:29:10 +08:00
@wutiantong
我对标准了解的不深,说不上哪边是对的…我也没有 msvc 环境,上面的修改是根据经验改的😂

不过从你描述的现象来看,msvc 需要触发 unit 的实例化才能输出期望的结果。
Wirbelwind
2020-11-26 13:27:32 +08:00
@wutiantong 不是构造函数的问题

在初始化的时候需要调用 unit_val(),问题是编译器 什么时候 用 unit_val()的返回值对它赋值

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/729105

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX