我试图写一个特征来检查一个类是否具有静态功能,但是它总是给我错误。谁能告诉我问题出在哪里?
#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;
}
这些示例之间似乎并没有太大差异。
任何人都可以让我理解第一个代码的问题在哪里吗?
答案 0 :(得分:0)
注意,C ++ 17 17.5.7.2表示
当template-id指代别名模板的特化时, 它等效于通过替换获得的关联类型 它的type-id中的template-parameters的template-arguments 别名模板。 [注意:不会推导别名模板名称。 - 结束语]
这是一个一步的过程,后续的模板参数替换在这里不再适用。
让我们开始第一个示例:
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
有趣的是,由于C ++ 17,17.5.7.3,您对void_t
的想法起作用了
但是,如果template-id是依赖的,则后续的模板参数 替换仍然适用于template-id
我建议尽可能使用基于结构而不是基于别名的模板。否则,使其工作就像点燃其自焚一样困难