为什么在某些情况下不能在没有强制转换的情况下引用公共静态常量变量?

Why can't a public static const variable be referenced in certain cases without a cast?

本文关键字:情况下 引用 静态 常量 变量 不能 为什么 转换      更新时间:2023-10-16

下面的代码说明了我遇到的一个问题,它无法使用对Def::DEFAULT;

的未定义引用进行编译

然而,如果我注释掉main中的第二行,它将编译并运行良好,我能够"看到"通过强制转换为int或直接分配给Val类int数据成员分配给DEFAULT的值。

template <typename T, T def>
class Def {
 public:
    static const T DEFAULT = def;
    enum {DEFAULT_ENUM = DEFAULT};
};

class Val {
 public:
    Val& operator=(const int &val_in) {
        val = val_in;
        return *this;
    }
    int val;
};

typedef Def<int, 10> Def_t;
Val test_val;
int main()
{
    test_val     =       Def_t::DEFAULT_ENUM;  // works
    test_val     =       Def_t::DEFAULT;       // fails to compile
    test_val     = (int) Def_t::DEFAULT;       // works
    test_val.val =       Def_t::DEFAULT;       // works
}

你的代码有未定义的行为,因为你使用Def_t::DEFAULT没有定义它[basic.def.odr]/3:

每个程序应该只包含一个在该程序中使用的非内联函数或变量的定义;不需要诊断。

类定义中的声明不是定义[class.static.data]/2:

静态数据成员在类定义中的声明不是定义... .静态数据成员的定义应该出现在包含该成员类定义的命名空间作用域中. ...

如果您的代码仍然不编译时,您添加Def_t::DEFAULT的声明,那么这是一个错误在您的编译器。可以通过在名称空间作用域中放置以下内容来添加定义:

template<typename T, T def>
T const Def<T, def>::DEFAULT;

如果您希望在T不是整型或枚举类型的情况下工作,请将DEFAULT的初始化器放在此命名空间作用域定义中,而不是放在类定义中。