C++ 在类型特征中,为什么人们对值使用enum而不是static const?
例如,这就是我编写它的方式,它编译并工作得很好:C++ 在类型特征中,为什么人们对值使用enum而不是static const?,c++,templates,enums,static,constants,C++,Templates,Enums,Static,Constants,例如,这就是我编写它的方式,它编译并工作得很好: template<typename T> struct is_pointer<T*> { static const bool value = true; } 模板结构是\u指针{ 静态常量布尔值=真; } 那为什么有些人写的不那么明显呢 template<typename T> struct is_pointer<T*> { enum { value = true }; }
template<typename T> struct is_pointer<T*> {
static const bool value = true;
}
模板结构是\u指针{
静态常量布尔值=真;
}
那为什么有些人写的不那么明显呢
template<typename T> struct is_pointer<T*> {
enum { value = true };
}
模板结构是\u指针{
枚举{value=true};
}
相反?这仅仅是因为static const
变量使用了一个字节的内存,而enum
没有吗
这仅仅是因为static const
变量使用了一个字节的内存,而enum
没有吗
是的,这就是原因
static const bool value = true;
会占用内存,而
enum { value = true };
不正确。是的,您是正确的:
enum{value=true}代码>不占用任何内存
此外,在C++11之前,它几乎是实现这一点的唯一方法:static const bool value=true代码>仅在C++11以后的类定义中是合法的。尽管可能首选constexpr
。一个显著的区别在于以下代码编译和链接:
template<typename>
struct is_pointer { };
template<typename T>
struct is_pointer<T*> {
enum { value = true };
};
void f(const bool &b) { }
int main() {
f(is_pointer<void*>::value);
}
当然,除非您在某处添加以下行,否则它不会起作用:
template<typename T>
const bool is_pointer<T*>::value;
这不起作用,这就是我发现它们之间细微差别的原因
我在这里找到了帮助,因此从我得到的答案中得到了一些很好的提示。
参考标准是一个加号,可以更好地解释引擎盖下发生了什么
请注意,像上面这样的静态constexpr
数据成员声明也是自C++17以来的定义。因此,您不必再定义它,而是可以直接使用odr
正如评论中提到的(感谢@Yakk证实了这一点),我还试图解释上面提到的命名常量如何绑定到常量引用
介绍整数常量表达式,并提到unscopedenum
s,表示它隐式转换为prvalue。
剩下的就做,因为它们对引用绑定和临时性进行规则。它也是包含它的每个对象文件中的另一个符号,没有任何好处。如果使用符号折叠(--gc sections),您将用完可分离的部分并使二进制文件膨胀。有些人编写不太明显的enum
,而不是静态bool const
,因为他们没有意识到他们应该进行其他更改
如果需要对象的地址,C++要求定义该对象,例如,如果该对象被传递到此函数foo
:
void foo(bool const &);
但是,通过定义对象来解决问题实际上并不是解决此问题的正确方法。以下是一些备选方案:
。更改应该是从函数签名中删除const&
,而不是添加对象的定义
如果无法更改函数签名,则可以在调用中显式创建临时签名:foo(bool{Cls::mbr})
但是,这是编译时信息!因此,foo
应该是一个带有T
和T*
重载的模板,或者专用于bool
第三种解决方案的好处是删除了不必要的运行时检查(希望由编译器优化),还允许独立处理指针和非指针大小写,可能使代码更清晰。不幸的是(?)这不是其中一种优于另一种的唯一原因。;-)<代码>静态常量布尔值=真代码>,在类定义中,不占用任何内存。内存将被相应的类外定义占据,但是只有当<>代码>值>代码是ODR使用时才是必要的。按照@ M.M的注释,它更复杂,甚至更复杂,因为C++ +11不幸(?)这不是唯一的原因,哪一个比另一个更好。你有没有“只从C++ 11起法律作用”的参考?我相信“静态const”成员一直是C++语言以来的98。也许芭丝谢芭想的是NSDMI,但这与投票无关。OP应该接受这个答案而不是我的答案。我相信C++17内联变量可以解决这个问题。@Bathsheba这与我的一个问题非常相似,当我问这个问题时,我做了研究。类似的答案也适用于我的问题。@Thomas:静态
数据成员实际上只存在于内存中,如果定义了它们,则需要使用它们的地址(通过指针或引用)。节省内存是件好事,链接器抱怨你忘记了定义是件很烦人的事。@skypjack似乎很合理。很有趣,但我不确定这些是如何回答这个问题的。。。问题中的“const&
”、“函数签名”和“foo
”?@Thomas感谢您强调这一点。我肯定你猜到了,我指的是其他答案的内容。更好的练习,让答案变得自足。啊,思想的飞跃只发生在一个人的头脑中,而没有意识到它。我知道这一切。现在我明白你的意思了,好东西!
template<typename T>
struct is_pointer<T*> { static constexpr bool value = true; };
void foo(bool const &);