這些天我在用SFINAE做實驗,還有一些讓我感到困惑。爲什麼my_type_a
不能在my_function
的實例化中推導出來?SFINAE和模板函數實例化:爲什麼在使用具有SFINAE的類型的函數參數中使用模板參數時不能推導出來?
class my_type_a {};
template <typename T>
class my_common_type {
public:
constexpr static const bool valid = false;
};
template <>
class my_common_type<my_type_a> {
public:
constexpr static const bool valid = true;
using type = my_type_a;
};
template <typename T> using my_common_type_t = typename my_common_type<T>::type;
template <typename T, typename V>
void my_function(my_common_type_t<T> my_cvalue, V my_value) {}
int main(void) {
my_function(my_type_a(), 1.0);
}
G ++給了我這樣的:
/home/flisboac/test-template-template-arg-subst.cpp: In function ‘int main()’:
/home/flisboac/test-template-template-arg-subst.cpp:21:30: error: no matching function for call to ‘my_function(my_type_a, double)’
my_function(my_type_a(), 1.0);
^
/home/flisboac/test-template-template-arg-subst.cpp:18:6: note: candidate: template<class T, class V> void my_function(my_common_type_t<T>, V)
void my_function(my_common_type_t<T> my_type, V my_value) {}
^~~~~~~~~~~
/home/flisboac/test-template-template-arg-subst.cpp:18:6: note: template argument deduction/substitution failed:
/home/flisboac/test-template-template-arg-subst.cpp:21:30: note: couldn't deduce template parameter ‘T’
my_function(my_type_a(), 1.0);
^
我所期待的是,在調用my_function
當我在main
一樣,T
會被推斷爲函數的第一個參數的類型,以及該類型將用於函數的實例化。但似乎my_common_type_t<T>
是函數之前實例化,但即使如此,中my_cvalue
類型將成爲my_type_a
反正,所以我不明白爲什麼這是行不通的......
是否有不同的方式來做到這一點?我應該避免兩個(或更多)級別的模板間接?
在'my_common_type :: type'中,'T'在[非推導的上下文](http://en.cppreference.com/w/cpp/language/template_argument_deduction#Non-deduced_contexts)中。你希望編譯器用每個可能的類型'T'實例化'my_common_type',希望其中的一個'my_common_type :: type'出來與'my_type_a'兼容;或者參與定理證明練習以嘗試並通過分析找到這種類型。編譯器不會。 –
@Igor我明白規則1(來自您提供的鏈接)當然符合我的例子。但是,爲什麼不清楚'T'不一定是'my_type_a'?如果'my_common_type'在實例化'my_function'之前被實例化,那麼類型可能是'my_type_a'或者什麼也不是(因此函數將通過SFINAE消除)。如果在編譯期間或之後實例化,編譯器會將'my_common_type '的信息作爲候選(因此,'T = my_type_a'),是不是? –
*「爲什麼不清楚」*這是我說的定理證明練習。這裏的「清除」意味着「可以從現有事實中證明」。也許它可以 - 但編譯器不需要擁有這種推理引擎。 –