I'm experimenting with C++11, constexpr and auto.
I'm failing to understand why this code does not compile:
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
Without definition I have linking problems. I know this problem has been fixed in C++17 but better understand fully C++11 now
[Edit] Error message is:
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 using GCC 4.8.5
Consider the following a long comment instead of an answer (sorry).
I don't know who is right (MSVS that accept all, g++ that accept f
but refuse g
or clang++ that refuse both f
and g
) but, if I understand correctly, this is a simplification of a more complex problem that you can't solve simply using int
and int *
instead of auto
.
So I propose to insert a couple of types inside TestEle2
using typeF = decltype(5);
using typeG = decltype(&DStruct<char, t>::a);
and use them instead of auto
and decltype()
for f
and g
types.
The following is a full compiling (both g++ and c++; I don't know MSVS (sorry)) example
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()
{
}