在模板参数中查找类型名称的类型名称

find typename of typename in template parameter

本文关键字:类型 查找 参数      更新时间:2023-10-16

我希望当foo从base获取任何派生内容时编译以下代码,否则会出现编译错误。我已经编写了类型特征类is_Base因为std::is_base_of不能很好地与我的模板内容配合使用。我很接近。我用static_passoff的东西让它工作,但我想不必使用它。那么,如果没有static_passoff黑客,如何编写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不需要定义。只是宣言。我们实际上并没有调用它,只是检查它的返回类型。它也不必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&)
{
}

在盲目地进入评论中的答案后,我发现我可以在没有任何typename关键字的情况下使用is_Base<T>::type::value。之前尝试删除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;
}