在C++ 11中,如何專用一個使用decltype聲明「複雜」尾隨返回類型的函數模板?在GCC下面的作品,但產生「錯誤C2912:明確的專業化‘詮釋F(無效)’不是一個函數模板的一個特例」,在VC2013:具有decltype追蹤返回類型的專用函數模板
#include <iostream>
int myint() { return 1; }
template<class T>
auto f() -> decltype(myint()) // this seems to cause problems
{
std::cout << "general\n";
return 1;
}
template <>
auto f<double>() -> decltype(myint())
{
std::cout << "special\n";
return 2;
}
int main()
{
f<int>();
f<double>(); // compiler error in VC, but not in GCC
}
我說「複雜」,在缺乏技術上精確因爲我不確定是什麼造成了差異。例如,下面的decltype,和使用內置不依賴於任何函數的結果類型操作,正常工作與模板特:
自動F() - > decltype(1 + 1)
所以,我的問題(所有相關的):
- 我的代碼是否正確C++ 11?
- 這是一個VC錯誤?
- 如果這種專業化不起作用,我怎麼能爲一個不可改變的遺留容器類專門化std :: begin和std :: end(從而提供基於範圍的循環)?
感謝typedef的把戲,這絕對是新的我!我仍然試圖理解C++ 11中關於std :: begin等的真正習慣用法。也許如果我的主要擔心是提供基於範圍的for循環,我不應該太在意std :: begin/std :: end並且只提供獨立的非std begin/end函數? –
@ChristianHackl對於舊的C風格數組(例如'int v [42];'),獨立的'std :: begin()'和'std :: end()'方便。如果你想讓你的舊容器使用新的基於範圍的for循環,只需提供'my_container.begin()'和'my_container.end()'* member *函數。假設你可以更換舊容器,但是你寫的不可更改......嗯。或者,您可以爲這些舊容器定義視圖,而不需要更改舊代碼。無論如何,如果一個簡單的typedef足夠了,我會去typedef。 – Ali
我正在考慮沿着同樣的路線...... LegacyContainerLoopAdapter用begin()/ end()成員函數包裝LegacyContainer。但是,當然,std :: begin/std :: end對於更高級的泛化類型也是很方便的(比如像bool empty(T const&c){return std :: begin(c)= = std :: end(c);})。這就是爲什麼我認爲專業std :: begin和std :: end永遠是最好的方法。 –