2015-10-26 20 views
5

Mam problem z statycznym członkiem constexpr szablonu struct. Kod się kompiluje, ale pojawia się błąd łączenia. Oto, co usiłuję zrobić:Niezdefiniowane odwołanie, szablon struct i constexpr static member

template<int n> 
struct Test { 
    static constexpr auto invoke = make_tuple(2, "test", 3.4); 
}; 

template<typename T> 
void test(T&& t) { 
    cout << t << endl; 
} 

int main() { 
    test(get<0>(Test<2>::invoke)); 
    return 0; 
} 

mam łączenie błędy z tym, więc próbowałem to:

template<int n> 
struct Test { 
    static constexpr auto invoke = make_tuple(2, "test", 3.4); 
}; 

// declare it outside the class 
template<int n> 
constexpr decltype(Test<n>::invoke) Test<n>::invoke; 

template<typename T> 
void test(T&& t) { 
    cout << t << endl; 
} 

int main() { 
    test(get<0>(Test<2>::invoke)); 
    return 0; 
} 

Ale zamiast tego mam ten dziwny błąd:

error: redefinition of 'invoke' with a different type: 'const decltype(Test<n>::invoke)' vs 'const std::tuple<int, const char *, double>' 

Inny typ? Oczywiście, wersja non-szablon działa dobrze:

struct Test { 
    static constexpr auto invoke = make_tuple(2, "test", 3.4); 
}; 

constexpr decltype(Test::invoke) Test::invoke; 

template<typename T> 
void test(T&& t) { 
    cout << t << endl; 
} 

int main() { 
    test(get<0>(Test::invoke)); 
    return 0; 
} 

Jak mogę dostać wersję szablon do pracy? Dziękuję bardzo

+0

Dodałem C++ 14, ponieważ 'make_tuple' nie jest constexpr do tego czasu. –

Odpowiedz

1

How can I get the template version to work?

FWIW, twoja metoda działa dobrze na moim pulpicie, który używa g ++ 4.8.4.

Można użyć:

template<int n> 
constexpr decltype(make_tuple(2, "test", 3.4)) Test<n>::invoke; 

następujące prace również na pulpicie:

template<int n> 
struct Test { 
    static constexpr auto invoke = make_tuple(2, "test", 3.4); 
    typedef decltype(invoke) invoke_t; 
}; 

template<int n> 
constexpr typename Test<n>::invoke_t Test<n>::invoke; 
+1

Jedynym rozwiązaniem, które wydaje się działać, jest 'decltype (make_tuple (2," test ", 3.4))' Używam GCC 5.2.0 i Clang 3.7.0 –

+0

To dziwne, że g ++ 5.2.0 nie działa podczas g ++ 4.8.4 działa. –

3

Wygląda jak używasz do interesującej przypadku rogu z decltype, jest pokryte w brzękiem raport o błędzie Static constexpr definitions used inside template, który ma następujący przykład z podobnym błędem jak Twój:

This compiles fine, but when I make the class A, a template like this:

struct L 
{ 
    void operator()() const 
    {} 
}; 

template<class X> 
struct A 
{ 
    static constexpr auto F = L(); 
}; 

template<class X> 
constexpr decltype(A<X>::F) A<X>::F; 

int main() 
{ 
    A<void>::F(); 
    return 0; 
} 

Clang crashes, if I change the definition line for F to this:

template<class X> 
constexpr typename std::remove_const<decltype(A<X>::F)>::type A<X>::F; 

Then clang produces this error:

error: redefinition of 'F' with a different type 
constexpr typename std::remove_const<decltype(A<X>::F)>::type A<X>::F; 
                    ^
note: previous definition is here 
    static constexpr auto F = L(); 
         ^

i odpowiedź Richarda Smitha był następujący:

This error is correct. 'constexpr' and 'auto' are red herrings here. Reduced testcase:

template<class X> struct A { static int F; }; 
template<class X> decltype(A<X>::F) A<X>::F; 

Per C++11 [temp.type]p2, "If an expression e involves a template parameter, decltype(e) denotes a unique dependent type." Therefore the type of A::F does not match the type in the template.

pełny cytat za to z projektu C++ 14 jest następująca:

If an expression e involves a template parameter, decltype(e) denotes a unique dependent type. Two such decltype-specifiers refer to the same type only if their expressions are equivalent (14.5.6.1). [ Note: however, it may be aliased, e.g., by a typedef-name. —end note ]

Jedynym oczywistym sposobem widzę, aby to praca to:

template<int n> 
constexpr decltype(make_tuple(2, "test", 3.4)) Test<n>::invoke; 

W raporcie o błędzie nie podano żadnej pracy.

Powiązane problemy