`static constexpr auto` data-member用未命名的枚举初始化 [英] `static constexpr auto` data-member initialized with unnamed enum

查看:304
本文介绍了`static constexpr auto` data-member用未命名的枚举初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个C ++ 11项目,仅使用 clang ++ - 3.4 ,并决定使用 g ++ - 4.8.2 如果产生错误有任何差异。原来,g ++拒绝了一些++ ++接受的代码。我已经将问题减少到下面给出的MWE。






 枚举{a} ; 

模板< class T>
struct foo
{
static constexpr auto value = a;
};

int main()
{
static constexpr auto r = foo< int> :: value;
}


foo.cpp:5:23:error:' const< anonymous枚举>使用匿名类型声明的foo< int> :: value ',但从未定义[-fpermissive]

  static const auto value = A; 







像一些帮助回答以下两个问题:




  • 哪个编译器在标准解释中是正确的?我假设一个编译器正确接受或拒绝代码,另一个是错误的。


  • 我如何解决这个问题?我不能命名匿名枚举,因为它来自第三方库(在我的例子中,枚举是 Eigen :: RowMajor Eigen :: ColMajor )。



解决方案

谁负责?



GCC 不正确地拒绝您的代码段,根据C ++ 11标准(N3337)。



解决方法(A) - 添加缺少的定义

 模板< class T> 
struct foo {
static constexpr auto value = a;
typedef decltype(a)value_type;
};

模板< class T>
constexpr typename foo< T> :: value_type foo< T> :: value;




解决方法(B) - 将枚举的底层类型用作占位符

  #include< type_traits> 

模板< class T>
struct foo {
static const std :: underlying_type< decltype(a)> :: type value = a;
};






标准是什么? ( N3337



如上所述,代码段是合法的,它可以在以下引用的部分阅读。






我们什么时候可以使用没有链接的类型?



[basic.link] p8 具有描述什么时候类型是无连接的详细措辞,它表示一个未命名的枚举计数是这样的。 / p>

[basic.link] p8 还明确指出了这样的类型不能使用的三个上下文,但不是其中之一上下文适用于我们的使用,所以我们是安全的。



没有链接的类型不能用作具有外部链接的变量或函数的类型,除非




  • 实体具有C语言链接(7.5)或

  • 该实体在未命名的内部声明命名空间(7.3.1)或

  • 实体不是 odr-使用(3.2)或在同一个翻译单位中定义






您确定我们可以在这样的上下文中使用 auto h3>

是的,这可以通过以下引用证明:


7.1.6.4p auto 说明符 [dcl.spec.auto] / code>


A auto type-specifier 也可以用于在con中声明一个变量 new-type-id 类型中的 type-specifier-seq 中的选择语句(6.4)或迭代语句(6.5) id (5.3.4)中,在范围声明中,并声明静态数据成员使用一个类定义(9.4.2)的成员规范中显示的大括号或相等初始化器




I was working on a C++11 project solely using clang++-3.4, and decided to compile using g++-4.8.2 in case there were any discrepancies in the errors produced. It turned out that g++ rejects some code that clang++ accepts. I have reduced the problem to the MWE given below.


enum { a };

template <class T>
struct foo
{
    static constexpr auto value = a;
};

int main()
{
    static constexpr auto r = foo<int>::value;
}

foo.cpp:5:23: error: ‘const<anonymous enum> foo<int>::value’, declared using anonymous type, is used but never defined [-fpermissive]

static const auto value = A;


I would like some help answering the following two questions:

  • Which compiler is correct in its interpretation of the standard? I am assuming that one compiler is right in either accepting or rejecting the code, and the other is wrong.

  • How can I work around this issue? I can't name the anonymous enum, because it is from a third-party library (in my case, the enums were Eigen::RowMajor and Eigen::ColMajor).

解决方案

Who's to blame?

GCC is inaccurately rejecting your snippet, it is legal according to the C++11 Standard (N3337). Quotations with proof and explanation is located the end of this post.

workaround (A) - add the missing definition

template <class T>
struct foo {
    static constexpr auto value = a;
    typedef decltype(a) value_type;
};

template<class T>
constexpr typename foo<T>::value_type foo<T>::value;


workaround (B) - use the underlying-type of the enumeration as placeholder

#include <type_traits>

template <class T>
struct foo {
  static const std::underlying_type<decltype(a)>::type value = a;
};


What does the Standard say? (N3337)

As stated, the snippet is legal C++11, as can be read in the following quoted sections.


When can we use a type without linkage?

[basic.link]p8 has detailed wording that describes when a type is "without linkage", and it states that an unnamed enumeration count as such type.

[basic.link]p8 also explicitly states three contexts where such a type cannot be used, but not one of the contexts apply to our usage, so we are safe.

A type without linkage shall not be used as the type of a variable or function with external linkage unless

  • the entity has C language linkage (7.5), or
  • the entity is declared within an unnamed namespace (7.3.1), or
  • the entity is not odr-used (3.2) or is defined in the same translation unit


Are you sure we can use auto in such context?

Yes, and this can be proven by the following quote:

7.1.6.4p auto specifier [dcl.spec.auto]

A auto type-specifier can also be used in declaring a variable in the condition of a selection statement (6.4) or an iteration statement (6.5), in the type-specifier-seq in the new-type-id or type-id of a new-expression (5.3.4), in a for-range-declaration, and in declaring a static data member with a brace-or-equal-initializer that appears within the member-specification of a class definition (9.4.2).

这篇关于`static constexpr auto` data-member用未命名的枚举初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆