2016-01-24 88 views
5

我想在一個頭文件中轉發聲明變量模板,然後在單獨的編譯單元中有實際的實例。無法聲明模板變量而不定義它

我被帶到相信C++ 14變量模板非常像靜態類變量那樣操作。不幸的是,這似乎並不是這樣,它阻止了我向前聲明我的變量模板。

template <typename T> struct Variable { 
    static int variable; 
}; 

template <typename T> 
extern int variable; 

int main() { 
    (void) Variable<char>::variable; 
    // (void) variable<char>;     // <-- line 10 
} 

template <> int Variable<char>::variable = 42; 
template <> int variable<char> = 23; 

上面的代碼示例在GCC下編譯並按原樣運行。但取消註釋第10行給出了編譯時錯誤:

specialization of 'variable<char>' after instantiation 
    template <> int variable<char> = 23; 
        ^
+1

Clang拒絕這兩個。這是不合格的NDR。顯式*實例化*和顯式*特化*是完全不同的野獸。 –

+0

好的 - 那麼怎麼做*我完成了我想要的 - 即在頭文件中聲明變量,但在.cpp中定義它? –

回答

1

我認爲你是在正確的軌道上。

技巧是這樣的:在任何一個翻譯單元中,不要在專業化之前實例化模板。

例如:

// test.h 
#ifndef TEST_H 
#define TEST_H 

template <typename T> 
extern int variable; 

template <> extern int variable<char>; 
template <> extern int variable<int>; 

#endif // TEST_H 

然後:

// test2.cpp 
#include "test.h" 

template <> int variable<char> = 23; 
template <> int variable<int> = 24; 

最後:

// test.cpp 
#include "test.h" 
#include <iostream> 

int 
main() 
{ 
    std::cout << variable<char> << '\n'; 
    std::cout << variable<int> << '\n'; 
} 

對於我這種輸出:

23 
24 

更新

T.C.在下面的評論中指出,專業化需要在第一次使用之前聲明,所以我已經更新了上面的「test.h」來做到這一點。

更新2

似乎有一些分歧的實現。鐺似乎處理這個罰款:

template <typename T> 
extern int variable; 

template <> extern int variable<char>; 
template <> extern int variable<int>; 

#include <iostream> 

int 
main() 
{ 
    std::cout << variable<char> << '\n'; 
    std::cout << variable<int> << '\n'; 
} 

template <> int variable<char> = 23; 
template <> int variable<int> = 24; 

http://melpon.org/wandbox/permlink/DGYKvvoPbmRIHaFi

但是GCC給出了一個錯誤:

prog.cc:4:13: error: explicit template specialization cannot have a storage class 
template <> extern int variable<char>; 
      ^~~~~~ 

prog.cc:5:13: error: explicit template specialization cannot have a storage class 
template <> extern int variable<int>; 
      ^~~~~~ 

我搜索的標準和核心問題列表,我無法找到任何指示一個編譯器或另一個編譯器是正確的。如果有人看到這樣的證據,我很樂意將它包含在這個答案中。

+0

這仍然是[格式不正確的NDR](http://eel.is/c++draft/temp.expl.spec#6)。我們需要的是在頭文件中聲明明確的特化,但我不確定OP是否實際上意味着明確地專門化模板。 –

+0

@ T.C .:謝謝,修正。 –

+0

這仍然不起作用 - 這是代碼。 https://github.com/rec/variable-template它在叮噹中完全不起作用;在g ++ 5.3.0上,它編譯但打印0和0; 「統一」版本也不能編譯。 –