在模板参数中查找 typename 的 typename
find typename of typename in template parameter
我希望以下代码在 foo 从 base 派生任何东西时进行编译,否则会出现编译错误。我写了类型特征 class is_Base 因为 std::is_base_of
不能很好地与我的模板内容一起使用。我很接近。我使用 static_passoff
东西让它工作,但我不想使用它。那么如何在没有 static_passoff
hack 的情况下编写 enable_if 呢?这是 运行 版本:http://coliru.stacked-crooked.com/a/6de5171b6d3e12ff
#include <iostream>
#include <memory>
using namespace std;
template < typename D >
class Base
{
public:
typedef D EType;
};
template<class T>
struct is_Base
{
using base_type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<class U>
static constexpr std::true_type test(Base<U> *) { return std::true_type(); }
static constexpr std::false_type test(...) { return std::false_type(); }
using value = decltype( test((T*)0) );
};
template < typename A >
using static_passoff = std::integral_constant< bool, A::value >;
template <typename T, typename = typename std::enable_if< static_passoff< typename is_Base< T >::value >::value >::type >
void foo(T const&)
{
}
class Derived : public Base<Derived> {};
class NotDerived {};
int main()
{
Derived d;
//NotDerived nd;
foo(d);
//foo(nd); // <-- Should cause compile error
return 0;
}
鉴于您的代码确实有效,我不确定我是否理解您的问题。但从风格上讲,对于产生类型的元函数,该类型应该命名为 type
。所以你应该:
using type = decltype( test((T*)0) );
^^^^
或者,为了避免零指针强制转换:
using type = decltype(test(std::declval<T*>()));
此外,您的 test
不需要定义。只是声明。我们实际上并没有 调用 它,只是检查它的 return 类型。它也不一定是 constexpr
,所以这就足够了:
template<class U>
static std::true_type test(Base<U> *);
static std::false_type test(...);
一旦你有了它,你可以给它起别名:
template <typename T>
using is_Base_t = typename is_Base<T>::type;
并使用别名:
template <typename T,
typename = std::enable_if_t< is_Base_t<T>::value>>
void foo(T const&)
{
}
在盲目地找到评论中的答案后,我发现我可以只使用 is_Base<T>::type::value
而没有任何 typename
关键字。之前尝试删除static_passoff
时,我一直在输入typename
。我一直和那个混在一起。无论如何,这是最终代码,其中包含 Barry 的回答中的一些柚木:
#include <iostream>
#include <memory>
using namespace std;
template < typename D >
class Base
{
public:
typedef D EType;
};
template<class T>
struct is_Base
{
using base_type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<class U>
static constexpr std::true_type test(Base<U> *) { return std::true_type(); }
static constexpr std::false_type test(...) { return std::false_type(); }
using type = decltype(test(std::declval<T*>()));
};
template <typename T, typename = typename std::enable_if< is_Base< T >::type::value >::type >
void foo(T const&)
{
}
class Derived : public Base<Derived> {};
class NotDerived {};
int main()
{
Derived d;
//NotDerived nd;
foo(d);
//foo(nd); // <-- Should cause compile error
return 0;
}
我希望以下代码在 foo 从 base 派生任何东西时进行编译,否则会出现编译错误。我写了类型特征 class is_Base 因为 std::is_base_of
不能很好地与我的模板内容一起使用。我很接近。我使用 static_passoff
东西让它工作,但我不想使用它。那么如何在没有 static_passoff
hack 的情况下编写 enable_if 呢?这是 运行 版本:http://coliru.stacked-crooked.com/a/6de5171b6d3e12ff
#include <iostream>
#include <memory>
using namespace std;
template < typename D >
class Base
{
public:
typedef D EType;
};
template<class T>
struct is_Base
{
using base_type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<class U>
static constexpr std::true_type test(Base<U> *) { return std::true_type(); }
static constexpr std::false_type test(...) { return std::false_type(); }
using value = decltype( test((T*)0) );
};
template < typename A >
using static_passoff = std::integral_constant< bool, A::value >;
template <typename T, typename = typename std::enable_if< static_passoff< typename is_Base< T >::value >::value >::type >
void foo(T const&)
{
}
class Derived : public Base<Derived> {};
class NotDerived {};
int main()
{
Derived d;
//NotDerived nd;
foo(d);
//foo(nd); // <-- Should cause compile error
return 0;
}
鉴于您的代码确实有效,我不确定我是否理解您的问题。但从风格上讲,对于产生类型的元函数,该类型应该命名为 type
。所以你应该:
using type = decltype( test((T*)0) );
^^^^
或者,为了避免零指针强制转换:
using type = decltype(test(std::declval<T*>()));
此外,您的 test
不需要定义。只是声明。我们实际上并没有 调用 它,只是检查它的 return 类型。它也不一定是 constexpr
,所以这就足够了:
template<class U>
static std::true_type test(Base<U> *);
static std::false_type test(...);
一旦你有了它,你可以给它起别名:
template <typename T>
using is_Base_t = typename is_Base<T>::type;
并使用别名:
template <typename T,
typename = std::enable_if_t< is_Base_t<T>::value>>
void foo(T const&)
{
}
在盲目地找到评论中的答案后,我发现我可以只使用 is_Base<T>::type::value
而没有任何 typename
关键字。之前尝试删除static_passoff
时,我一直在输入typename
。我一直和那个混在一起。无论如何,这是最终代码,其中包含 Barry 的回答中的一些柚木:
#include <iostream>
#include <memory>
using namespace std;
template < typename D >
class Base
{
public:
typedef D EType;
};
template<class T>
struct is_Base
{
using base_type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<class U>
static constexpr std::true_type test(Base<U> *) { return std::true_type(); }
static constexpr std::false_type test(...) { return std::false_type(); }
using type = decltype(test(std::declval<T*>()));
};
template <typename T, typename = typename std::enable_if< is_Base< T >::type::value >::type >
void foo(T const&)
{
}
class Derived : public Base<Derived> {};
class NotDerived {};
int main()
{
Derived d;
//NotDerived nd;
foo(d);
//foo(nd); // <-- Should cause compile error
return 0;
}