【问题标题】:Substitute fully instantiated classes with partially instantiated ancestor classes用部分实例化的祖先类替换完全实例化的类
【发布时间】:2013-04-01 09:06:37
【问题描述】:

当我在表单中给出模板参数时,我希望accepted_dense_vector<??>::value 返回'true':

C<T> 当C 是uvector、dynamic_array 和T 是std::is_arithmetic。

std::array<T,S> 当T 是std::is_arithmetic。

container_reference<C> 当accepted_dense_vector<C>::value 为“真”时。

一切正常,但在派生的、完全实例化的类 A、C、D 中,我想删除解决方法 parent 定义。

我该怎么做?

#include <iostream>
#include <array>
using namespace std;

// Definition of used types.
template<typename T> struct dynamic_array {};
template<typename T> struct uvector {};
struct A : public uvector<double> { typedef uvector<double> parent; };
struct C : public A { typedef A parent; };
struct D : public std::array<double,5> { typedef std::array<double,5> parent; };
template<typename T> struct B : public uvector<T> { typedef uvector<T> parent; };
template<typename T> struct container_reference {};

// Catches 'false', A, C, D  ======== HERE IT IS !!! ========
template<typename C> struct accepted_dense_vector
{
    template<typename C1 = C>
    static typename std::enable_if<accepted_dense_vector<typename C1::parent>::value, std::true_type>::type helper(const C&);
    static std::false_type helper(...);

    constexpr static bool value = decltype(helper(std::declval<C>()))::value;
};
// Catches C<T>
template<template<typename> class C, typename T>
struct accepted_dense_vector<C<T>>
{
    constexpr static bool value = std::is_arithmetic<T>::value &&
        (std::is_base_of<uvector<T>, C<T>>::value || std::is_base_of<dynamic_array<T>, C<T>>::value);
};
// Catches std::array<T,S>
template<typename T, size_t S>
struct accepted_dense_vector<std::array<T,S>>
    { constexpr static bool value = std::is_arithmetic<T>::value; };

// Catches container_reference<C>
template<typename C>
struct accepted_dense_vector<container_reference<C>>
    { constexpr static bool value = accepted_dense_vector<C>::value; };

int main()
{ // Tests!
    cout << accepted_dense_vector<std::array<double, 5>>::value << endl;
    cout << accepted_dense_vector<uvector<double>>::value << endl;
    cout << accepted_dense_vector<A>::value << endl;
    cout << accepted_dense_vector<D>::value << endl;
    cout << accepted_dense_vector<B<int>>::value << endl;
    cout << accepted_dense_vector<container_reference<uvector<double>>>::value << endl;
    cout << accepted_dense_vector<int>::value << endl;

    return 0;
}

【问题讨论】:

    标签: c++ templates inheritance instantiation sfinae


    【解决方案1】:

    您可以通过您的解决方案走得更远。首先,您不需要std::enable_if。代码将更具可读性。然后,不要使用std::true_type,而是使用将调用accepted_dense_vector 的自定义结构:

    template<typename T>
    struct forwarder
    {
        constexpr static bool value = accepted_dense_vector<T>::value;
    };
    
    template<typename T>
    static forwarder<uvector<T>> inherit_uvector(uvector<T>*);
    
    static std::false_type inherit_uvector(...);
    

    那么,要通过uvector&lt;T&gt;的继承来知道类型是否满足accepted...,只需使用以下行:

    constexpr static bool is_uvector = decltype(inherit_uvector(new C()))::value;
    // C is the template parameter of accepted_dense_vector
    

    这是如何工作的?

    • 如果C继承uvector&lt;T&gt;,则选择第一个静态函数,decltype将返回forwarder&lt;uvector&lt;T&gt;&gt;。然后,“呼叫”::value 将呼叫accepted...。
    • 否则,如果C不继承uvector&lt;T&gt;,则选择第二个函数,decltype将返回std::false_type。

    同样的技巧可以用于其他继承。此外,B&lt;T&gt; 被 accepted... 的第二个专业化捕获。因此,不再需要 ::parent 类型定义。

    这里是完整代码 (live here):

    #include <iostream>
    #include <array>
    #include <string>
    using namespace std;
    
    // Definition of used types.
    template<typename T> struct uvector {};
    template<typename T> struct dynamic_array {};
    template<typename T> struct container_reference {};
    
    struct A : public uvector<double> {};
    template<typename T> struct B : public uvector<T> {};
    struct C : public A {};
    struct D : public std::array<double,5> {};
    struct E : public uvector<string> {};
    struct F : public std::array<string,16> {};
    
    // Catches 'false', A, C, D  ======== HERE IT IS !!! ========
    template<typename C>
    struct accepted_dense_vector
    {
       template<typename T>
       struct forwarder
       {
          constexpr static bool value = accepted_dense_vector<T>::value;
       };
    
       // uvector
       template<typename T>
       static forwarder<uvector<T>> inherit_uvector(uvector<T>*);
       static std::false_type inherit_uvector(...);
    
       // std::array
       template<typename T, size_t S>
       static forwarder<std::array<T,S>> inherit_stdarray(std::array<T,S>*);
       static std::false_type inherit_stdarray(...);
    
       // same for dynamic_array<T>
    
        constexpr static bool is_uvector = decltype(inherit_uvector(new C()))::value;
        constexpr static bool is_stdarray = decltype(inherit_stdarray(new C()))::value;
        constexpr static bool value = is_uvector || is_stdarray;
    };
    
    
    // Catches C<T>
    // /!\ Also catches anything which is template<typename> class (for example, B)
    // => B::parent is not needed, because of the use of std::is_base_of
    template<template<typename> class C, typename T>
    struct accepted_dense_vector<C<T>>
    {
        constexpr static bool value = std::is_arithmetic<T>::value &&
            (std::is_base_of<uvector<T>, C<T>>::value || std::is_base_of<dynamic_array<T>, C<T>>::value);
    };
    
    // Catches std::array<T,S>
    template<typename T, size_t S>
    struct accepted_dense_vector<std::array<T,S>>
    {
       constexpr static bool value = std::is_arithmetic<T>::value;
    };
    
    // Catches container_reference<C>
    template<typename C>
    struct accepted_dense_vector<container_reference<C>>
    {
       constexpr static bool value = accepted_dense_vector<C>::value;
    };
    
    int main()
    { // Tests!
        cout << "array = " << accepted_dense_vector<std::array<double, 5>>::value << endl;
        cout << "uvector = " << accepted_dense_vector<uvector<double>>::value << endl;
        cout << "ref = " << accepted_dense_vector<container_reference<uvector<double>>>::value << endl;
        cout << "A = " << accepted_dense_vector<A>::value << endl;
        cout << "B = " << accepted_dense_vector<B<int>>::value << endl;
        cout << "C = " << accepted_dense_vector<C>::value << endl;
        cout << "D = " << accepted_dense_vector<D>::value << endl;
        cout << "E = " << accepted_dense_vector<E>::value << endl;
        cout << "F = " << accepted_dense_vector<F>::value << endl;
        cout << "int = " << accepted_dense_vector<int>::value << endl;
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-03
      • 1970-01-01
      • 2020-12-13
      • 2014-06-18
      • 2016-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多