Противоречивое объявление с использованием constexpr и auto в C ++ 11 - PullRequest
0 голосов
/ 24 января 2019

Я экспериментирую с C ++ 11, constexpr и auto.

Я не понимаю, почему этот код не компилируется:

  template<class T, T t>
  struct TestEle2
    {

    };

template<class T, T t>
  struct DStruct {int a;};

  template<char t>
  struct TestEle2<char, t>
    {
    static constexpr auto f = 5;

    static constexpr auto g = &DStruct<char, t>::a;
    };

  template<char c>
  constexpr decltype(TestEle2<char, c>::f)
    TestEle2<char, c>::f ; // This compiles

  template<char c>
  constexpr decltype(TestEle2<char, c>::g)
    TestEle2<char, c>::g ; // This does not compile

Без определения у меня есть ссылкипроблемы.Я знаю, что эта проблема была исправлена ​​в C ++ 17, но теперь я лучше понимаю C ++ 11

[Edit] Сообщение об ошибке:

error: conflicting declaration ‘constexpr decltype (TestEle2<char, t>::g) TestEle2<char, t>::g’
         TestEle2<char, c>::g ;
                            ^
error: ‘TestEle2<char, t>::g’ has a previous declaration as ‘constexpr const auto TestEle2<char, t>::g’
         static constexpr auto g = &DStruct<char, t>::a;
                               ^
error: declaration of ‘constexpr const auto TestEle2<char, t>::g’ outside of class is not definition [-fpermissive]

[Edit 2] I'mиспользуя GCC 4.8.5

1 Ответ

0 голосов
/ 24 января 2019

Рассмотрите следующий длинный комментарий вместо ответа (извините).

Я не знаю, кто прав (MSVS, которые принимают все, g ++, которые принимают f, но отказываются g или clang ++, которые отказываются как f, так и g), но, если я правильно понимаю, это упрощение более сложной проблемы, которую вы не можете решить, просто используя int и int * вместо auto.

Поэтому я предлагаю вставить пару типов внутрь TestEle2

using typeF = decltype(5);
using typeG = decltype(&DStruct<char, t>::a);

и используйте их вместо auto и decltype() для типов f и g.

Ниже приводится полная компиляция (как g ++, так и c ++; я не знаю MSVS (извините)) пример

template <class T, T t>
struct TestEle2
 { };

template <class T, T t>
struct DStruct
 { int a; };

template <char t>
struct TestEle2<char, t>
 {
   using typeF = decltype(5);
   using typeG = decltype(&DStruct<char, t>::a);

   static constexpr typeF f = 5;
   static constexpr typeG g = &DStruct<char, t>::a;
 };

// This compiles
template <char c>
constexpr typename TestEle2<char, c>::typeF TestEle2<char, c>::f; 

// This also compile
template <char c>
constexpr typename TestEle2<char, c>::typeG TestEle2<char, c>::g;

int main()
 {
 }
...