[英]Could anyone explain me why this trait does not work properly?
我試圖寫一個特征來檢查一個類是否具有靜態功能,但是它總是給我錯誤。 誰能告訴我問題出在哪里?
#include <iostream>
template <template <typename...> class Trait, typename Ret, typename T>
struct is_detected : std::false_type
{
//This helps me to check that Get_t<A> is int
static_assert(std::is_same<Trait<T>, Ret>::value, "");
};
template <template <typename...> class Trait, typename T>
struct is_detected<Trait, Trait<T>, T> : std::true_type {};
class A {
public:
static int Get() {
std::cout << "I'm in get\n";
return 0;
}
};
template <typename T>
using Get_t = decltype(T::Get());
//template <typename T>
//using supports_Get = is_detected<Get_t, int, T>;
int main() {
std::cout << is_detected<Get_t, int, A>::value << std::endl;
return 0;
}
以下代碼有效:
#include <iostream>
#include <type_traits>
namespace detail {
template <template <typename...> class Trait, typename V, typename T>
struct is_detected : std::false_type {};
template <template <typename...> class Trait, typename T>
struct is_detected<Trait, std::void_t<Trait<T>>, T> : std::true_type {};
}
class A {
public:
static int Get() {
std::cout << "I'm in get\n";
return 0;
}
};
template <typename T>
using Get_t = decltype(T::Get());
int main() {
std::cout << detail::is_detected<Get_t, void, A>::value << std::endl;
return 0;
}
這些示例之間似乎並沒有太大差異。
誰能讓我明白第一個代碼的問題在哪里?
注意C ++ 17,17.5.7.2說,
當template-id指代別名模板的特殊化時,它等效於通過將其模板參數替換為別名模板的type-id中的模板參數而獲得的關聯類型。 [注意:不會推導別名模板名稱。 —尾注]
這是一個一步的過程,后續的模板參數替換在此不再適用。
讓我們開始第一個示例:
template <template <typename> class Trait, typename Ret, typename T>
struct is_detected {};
struct A {
static int Get() {
return 0;
}
};
template <typename T>
using Get_t = decltype(T::Get());
template <typename T>
struct Get_t2 {
using Type = decltype(T::Get());
};
template <template <typename> class Trait, typename T>
struct is_detected<Trait, typename Trait<T>::Type, T> : std::true_type {};
template <template <typename> class Trait, typename T>
struct is_detected<Trait, Trait<T>, T> : std::true_type {};
現在您可以看到:
is_detected<Get_t2, int, A>::value // works, because it is normal type
is_detected<Get_t, int, A>::value // not, because it is alias
有趣的是與你的想法void_t
發揮作用是因為C ++ 17 17.5.7.3
但是,如果template-id是依賴的,則隨后的模板參數替換仍然適用於template-id
我建議盡可能使用基於結構而不是基於別名的模板。 否則,使其工作就像點燃其自焚一樣困難。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.