gpt4 book ai didi

c++ - 隐式实例化变量模板的动态初始化顺序

转载 作者:行者123 更新时间:2023-11-30 04:46:55 29 4
gpt4 key购买 nike

我针对我认为是 MSVC 中的错误提出了一个问题,但结果证明是实现定义的行为。我想确保我完全理解原因。我在一个翻译单元中有这个:

#include <limits>
#include <utility>
#include <type_traits>
#include <cmath>
#include <iostream>

struct MyClass {
double value_of;
MyClass(double d): value_of(d) {}
};

template<class T> struct MyTraits { static constexpr bool do_enable = false; };
template<> struct MyTraits<MyClass> { static constexpr bool do_enable = true; typedef double value_type; };

template<typename T> using EnableIfFP = std::enable_if_t<std::is_floating_point<T>::value>;
template<typename T> using EnableIfMyClass = std::enable_if_t<MyTraits<T>::do_enable>;

template<typename T> constexpr int EXP = std::numeric_limits<T>::max_exponent / 2;

template<typename T, typename Enabler = void> const T huge = T{ 0 };
template<typename T> const T huge<T, EnableIfFP<T> > = std::scalbn(1.0, EXP<T>);
template<typename T> const T huge<T, EnableIfMyClass<T> > = T{ huge<typename MyTraits<T>::value_type> };

int main() {
// huge<double>; // PRESENCE OF THIS LINE AFFECTS OUTPUT IN MSVC
std::cout << huge<MyClass>.value_of << std::endl;
return 0;
}

https://godbolt.org/z/Iwpwzf

我的期望是 huge<MyClass>.value_of为 1.34078e+154:huge 的第三个定义应该使用第二个定义作为它的初始化。 Clang 7、GCC 8 和 ICC 19 都这样做,但 MSVC 2017 打印 0(来自 T{ 0 } 或零初始化,idk),除非启用注释行。

据我所知,main()正在隐式实例化 huge<MyClass>和(间接)huge<double> ,但它们的初始化是无序的:

Dynamic initialization of a non-local variable with static storage duration is unordered if the variable is an implicitly or explicitly instantiated specialization, is partially-ordered if the variable is an inline variable that is not an implicitly or explicitly instantiated specialization, and otherwise is ordered. [Note: An explicitly specialized non-inline static data member or variable template specialization has ordered initialization. — end note] [basic.start.dynamic]

此场景符合我加粗的标准,因此它是无序的。最后有一条注释,我认为它的意思是“一个显式特化的变量模板特化已经有序初始化”,但我没有完全(明确地)特化,所以它不适用。

我还看到了this answer ,这似乎与规范的上述部分冲突:

Global variables in a single translation unit (source file) are initialized in the order in which they are defined.


  1. 以上推理是否正确?
  2. 想要 constexpr std::scalbn解决这个问题?
  3. 就使代码合法/可移植而言,当我尝试通过添加 template const MyClass huge<MyClass> 来显式实例化特化时,MSVC 发出声音。 .假装使用 huge<double>特化有效,但是是未使用的代码(GCC 警告)。我知道我可以改为在函数中创建这些静态局部变量(冒着添加锁/守卫的风险)或返回函数或类模板的值,但如果合法,此选项是最简洁的。

最佳答案

  1. 你是对的——“冲突”的答案完全早于变量模板。 (考虑到变量 template 不是“全局变量”,并且它的实例化没有以文本方式定义(,声明),该声明仍然正确。)<
  2. 是的,std::scalbn 是 constexpr 会有所帮助——它只是(有时)无序的动态 非局部初始化,并且如果变量的部分特化模板(文字类型)是用常量表达式初始化的,不会发生这种动态初始化。方便,such constexprification已获准用于 C++20,尽管它可能会或可能不会及时通过措辞审查。
  3. 在这里,再多的隐式或显式实例化都无济于事——正如您所引用的那样,只有显式特化才能做到这一点,或者将事物隐藏在函数中的各种技巧。您当然可以使用这些函数来初始化变量(以及可能在它们之前初始化的任何其他内容)并在其他任何地方使用这些变量。

关于c++ - 隐式实例化变量模板的动态初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56452118/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com