我知道模板成員函數僅在使用時纔會生成。如果不是所有使用的類型都支持這種功能,這很方便。但是,對於具有尾隨返回類型規範的函數,這似乎不起作用。下面是一個小實驗:具有結尾返回類型的模板成員函數,即使未使用也會出錯
// helper function for case A workaround
template <typename A, typename T>
auto F(T&& x)
-> decltype(x.template f <A>())
{ return x.template f <A>(); }
// helper function for case B workaround
template <typename A, typename T>
auto G(T&& x)
-> decltype(x.g())
{ return x.g(); }
template <typename T>
struct S
{
// case A: not ok in GCC + Clang
template <typename A>
auto f1()
-> decltype(T().template f <A>())
{ return T().template f <A>(); }
// case A workaround: ok in Clang + GCC
template <typename A>
auto f2()
-> decltype(F <A>(T()))
{ return F <A>(T()); }
// case B: ok in GCC, not ok in Clang
template <typename A>
auto g1()
-> decltype(T().g())
{ return T().g(); }
// case B workaround: ok in GCC + Clang
template <typename A>
auto g2()
-> decltype(G <A>(T()))
{ return G <A>(T()); }
};
請記住這個樣本只是爲了說明這個問題,它不是別的有用的。
S <T>
可以被實例化爲具有合適的成員函數f
,g
的任何類型T
。
但是,如果我嘗試實例化S <int>
,例如,通過S <int> s{};
,我確實收到錯誤,如type 'int' is not a structure or union
。這種情況發生在f1
,g1
這兩種情況下,它們試圖分別在T
(在這種情況下爲int
)的值上調用模板函數f
或非模板函數g
。即使我不試圖在對象s
上撥打f1
或g1
,也會發生這種情況。但是,GCC在g1
的情況下罰款;鏗鏘不是。
對於案例A(模板成員函數f
)的解決方法是使用幫助器函數F
,這是f2
所做的,並且對於Clang和GCC都可以正常工作。它似乎工作,因爲調用T().template f <A>()
對於f2
的聲明是隱藏的,編譯器在A
類型未知時未查找到F <A>(T())
。
案例B(非模板成員函數g
)的相同解決方法也適用於這兩種編譯器。
我希望能幫助您找出發生的一切。哪種情況下的正確行爲?哪個編譯器是正確的?總體來說還有其他解決方法嗎?
我正在使用GCC 4.8.1和Clang 3.3。
不是回答你的問題,而是'x.template˚F ()'一個合法的C++語句?它不應該只是'x.f ()' – Gasim
@Gasim它可能很醜,但不幸的是需要'template'關鍵字。例如'f'可能是一個數據成員,所以'x.f iavr
你知道['std :: enable_if'](http://en.cppreference.com/w/cpp/types/enable_if)嗎? – Constructor