2016-05-01 73 views
0

下面的程序工作得很好。我可以爲某些專業化定義靜態constexpr數據成員嗎?

#include <iostream> 
#include <type_traits> 

template <typename DummyT = void> 
struct wrapper 
{ 
    static_assert(std::is_same<void, DummyT>::value, "Only void, please"); 
    static constexpr char text[] = "some string constant"; 
}; 

template <typename DummyT> 
constexpr char wrapper<DummyT>::text[]; 

int 
main() 
{ 
    std::cout << wrapper<>::text << '\n'; 
} 

然而,當我只定義爲wrapper::textwrapper<void>

template <> 
constexpr char wrapper<void>::text[]; 

然後GCC 5.3.0給了我這個連接錯誤

/tmp/ccnGx3EP.o: In function `main': 
main.cxx:(.text+0x5): undefined reference to `wrapper<void>::text' 
collect2: error: ld returned 1 exit status 

和鏘3.7.1給了我這個錯誤。

main.cxx:12:31: error: declaration of constexpr static data member 'text' requires an initializer 
constexpr char wrapper<void>::text[]; 
          ^
1 error generated. 

我想知道爲什麼僅僅爲實際使用的專業化提供一個定義是不夠的。並不是說它會非常有用,因爲 constexpr成員必須在class定義中初始化,所以我無法將它定義在定義中,但我可能想讓它不確定。

+2

顯式特化有效地替換了主模板中的聲明/定義。 –

+0

@ T.C。我在假設靜態數據成員的類內初始化不是一個定義。所以不應該將模板體中的聲明+初始化應用於數據成員的所有類 - 模板的隱式實例化? –

+0

@ T.C。是的,我的直覺是對的:http://coliru.stacked-crooked.com/a/597464c14d48071f。所以,他的問題是他不能提供一個定義的專業化,而不提供一個初始化,因爲後者只聲明專業化。但是如果他做了後者,他會有兩個初始值。 –

回答

0

輕鬆:

template <typename DummyT = void> 
struct wrapper 
{ 
    static_assert(std::is_same<void, DummyT>::value, "Only void, please"); 
}; 

template <> 
struct wrapper<void> 
{ 
    static constexpr char text[] = "some string constant"; 
}; 

constexpr char wrapper<void>::text[]; 

兩個wrapper<>wrapper<void>將工作,而其他參數將與static_assert失敗。

+0

雖然這是一個很好的竅門,但我並沒有想到,不幸的是,將##包含到多個翻譯單元中並將它們連接在一起時會導致多重定義錯誤,從而減少了使用模板的目的「首先。 – 5gon12eder

+0

如果行「constexpr char wrapper :: text [];」多重定義問題消失了「被移入一個cpp(而不是頭文件)。這可以是編譯中使用的任何cpp文件,包括可能包含在它自己的只包含2個代碼行的cpp文件(#include語句加上定義本身) - 我需要提供靜態成員時多次親自使用後一種方法定義模板類。 – Smeeheey

相關問題