5

The following code compiles fine in GCC 6.3 with -std=c++11.

template <typename T>
struct MetaFunction
{
    static int value;
};

#define MY_MACRO(T) (MetaFunction<T>::value)

template <class T, const int* p = &MY_MACRO(T)>
struct Foo
{
    void DoSomething()
    {
    }
};

int main()
{
    Foo< int > f;
    f.DoSomething();
}

But if -std=c++14 is specified then it emits the following error:

main.cpp:19:14: error: '& MetaFunction<int>::value' is not a valid template argument for 'const int*' because it is not the address of a variable
     Foo< int > f;
              ^

Clang 3.8 gives a similar error whether -std=c++11 or -std=c++14 is specified.

main.cpp:11:36: error: non-type template argument does not refer to any declaration
template <class T, const int* p = &MY_MACRO(T)>
                                   ^~~~~~~~~~~

Changing MY_MACRO(T) from (MetaFunction<T>::value) to MetaFunction<T>::value fixes the problem.

Which compiler is correct here? Does the C++14 standard include a change that makes GCC's behaviour expected? Or is Clang right to emit an error under C++11 as well?

Andrew Durward
  • 3,771
  • 1
  • 19
  • 30
  • 2
    This is ill-formed in C++11 and C++14 as explained [here](http://stackoverflow.com/a/39778788/2756719). Not sure what GCC is playing at though. – T.C. Feb 15 '17 at 15:41
  • @Quentin No, that restriction is specific to non-static members (despite the horrible naming, "pointer to member" is all about non-static members; pointers to static members are just plain pointers). That is, `struct S { static int i; }; int* p = &(((((S::i)))));` is perfectly valid. – T.C. Feb 15 '17 at 15:43
  • @T.C. yes, yes it is... Glad I didn't dupe-hammer that one. Thanks for clearing that up. – Quentin Feb 15 '17 at 15:45
  • Side note: MSVS2015 also seems to have no problems with the code. even with `/std:c++14` or `/std:c++latest` – JHBonarius Feb 15 '17 at 16:37

0 Answers0