我一直在試圖理解C++選擇模板的方式。也就是說,考慮下面的代碼示例:會員功能模板選擇和SFINAE
template <typename R>
class Curious
{
public:
template <typename T, typename std::enable_if<std::is_const<T>::value, int>::type = 33>
void test1() {}
template <typename T, typename std::enable_if<!std::is_const<T>::value, int>::type = 33>
void test1() {}
template <typename T, typename = typename std::enable_if<std::is_const<T>::value>::type>
void test2() {}
template <typename T, typename = typename std::enable_if<!std::is_const<T>::value>::type>
void test2() {}
template <typename std::enable_if<std::is_const<R>::value>::type * = nullptr>
void test3() {}
template <typename std::enable_if<!std::is_const<R>::value>::type * = nullptr>
void test3() {}
// works
template <typename T = void>
typename std::enable_if<std::is_const<R>::value, T>::type test4() {}
template <typename T = void>
typename std::enable_if<!std::is_const<R>::value, T>::type test4() {}
// also works
template <typename T = void, typename std::enable_if<std::is_const<R>::value, T>::type * = nullptr>
void test5() {}
template <typename T = void, typename std::enable_if<!std::is_const<R>::value, T>::type * = nullptr>
void test5() {}
}; // Curious
前兩個功能(測試1)正常工作(爲什麼):
Curious<int> curious;
curious.test1<int>();
curious.test1<const int>();
雖然他們的休息導致編譯錯誤。 關於test2的編譯器要求我試圖創建一個重複的功能:
error C2535: 'void Curious::test2(void)': member function already defined or declared
Here的文件說:
一個常見的錯誤是聲明中的區別僅 二元函數模板,其默認模板參數。這是非法的,因爲默認 模板參數不是函數模板簽名的一部分,並且 聲明具有相同簽名的兩個不同函數模板是 非法。
所以它似乎是這種情況。但是,我沒有看到與前兩個函數有很大區別,它們也有默認的模板參數。因此,我們有一個默認類型(test2 - 不起作用)與默認值(test1 - works)。有關於它的規則嗎?
在test3的情況下:
error C2039: 'type': is not a member of 'std::enable_if'與第一種情況一樣,這次成員函數模板有一個默認的非類型參數,但它取決於類模板參數。現在SFINAE不會跳過錯誤的(也不知道爲什麼)。
在第四種情況下,SFINAE通過返回類型解析模板。但是這些test4函數不具有相同的簽名嗎?因爲它們僅在返回類型上有所不同。
據我所知,在第五種情況下,添加額外的參數使得test5簽名依賴於函數模板參數,因此SFINAE踢入和解析工作。
我很困惑C++如何處理這些模板。有人可以善待這些事嗎?
作爲一個說明,因爲C++ 14,你可以替換'類型名稱的std :: enable_if :: type'用'的std :: enable_if_t '。 –
Jarod42