Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在类型特征中,为什么人们对值使用enum而不是static const?_C++_Templates_Enums_Static_Constants - Fatal编程技术网

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证实了这一点),我还试图解释上面提到的命名常量如何绑定到常量引用

介绍整数常量表达式,并提到unscoped
enum
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 &);