以下代碼大部分摘自Piotr Skotnicki的answer。我用它進行試驗,發現了我認爲是MSVC 14.0更新錯誤3.當我更改類型參數名稱時,模板替換失敗 - 編譯器錯誤?
考慮下面的代碼:
#include <iostream>
template <typename T>
struct identity { using type = T; };
template <typename...>
using void_t = void;
template <typename F>
struct call_operator;
template <typename C, typename R, typename... A>
struct call_operator<R(C::*)(A...)> : identity<R(A...)> {};
template <typename C, typename R, typename... A>
struct call_operator<R(C::*)(A...) const> : identity<R(A...)> {};
template <typename F>
using call_operator_t = typename call_operator<F>::type;
template <typename, typename = void_t<>>
struct is_convertible_to_function
: std::false_type {};
template <typename L>
struct is_convertible_to_function<L, void_t<decltype(&L::operator())>>
: std::is_assignable<call_operator_t<decltype(&L::operator())>*&, L> {};
template <typename, typename = void_t<>>
struct is_callable_object
: std::false_type {};
template <typename L>
struct is_callable_object<L, void_t<decltype(&L::operator())>>
: std::true_type {};
int main()
{
auto x = []() {};
std::cout << std::boolalpha << is_callable_object<decltype(x)>::value;
std::getchar();
}
這將打印true
,符合市場預期,因爲所產生的拉姆達對象編譯器確實實現了operator()
。
現在讓我們在is_callable_object
從L
改變類型參數名稱T
(任何從is_convertible_to_function
導致此問題所使用的類型名稱不同,從我所看到的)。
template <typename, typename = void_t<>>
struct is_callable_object
: std::false_type {};
template <typename T>
struct is_callable_object<T, void_t<decltype(&T::operator())>>
: std::true_type {};
突然,這種打印false
。 is_convertible_to_funtion
應該無關緊要,因爲is_callable_object
不以任何方式依賴它;的確,如果我刪除is_convertible_to_function
,這個問題就會消失 - 我可以使用任何我想要的類型名稱。正如我所說,我懷疑這是一個錯誤,所以我問這個問題,以確保這不是在C++標準中的一些奇怪的行爲;解決這個問題的辦法很簡單。
我想知道您的聲明是不是太過分極端,但即使是微軟自己也承認:https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-表達-SFINAE-在-VS-2015-更新-1 /。哦,我會繼續試驗,謝謝。 – szczurcio