【问题标题】:Partial specialized template class (for container class type) is not called不调用部分专用模板类(用于容器类类型)
【发布时间】:2018-12-01 05:56:18
【问题描述】:

我仍在解决几个小时前发布的这个问题: [How to overload/specialize template class function to handle arithmetic types and a container-class 我试图实现这个解决方案。它可以编译,但对象是使用 DerivedClass-Constructor 而不是部分专用模板类 DerivedClass 创建的 你有什么想法我犯了一个(或一些)错误吗?

template <typename T> class BaseClass
{
protected:
  T mem;

public:
  BaseClass(T arg) : mem(arg){};
};

template <typename T> class DerivedClass : public BaseClass<T>
{
public:
  DerivedClass(T arg): BaseClass<T>(arg){};
};

template <typename T>
class DerivedClass<Eigen::ArrayBase<T> >
    : public DerivedClass<Eigen::ArrayBase<T> >
{
public: 
  DerivedClass(Eigen::ArrayBase<T> arg):BaseClass<Eigen::ArrayBase<T> >(arg){};
};

int main
{
...
  Eigen::Array3d arg = Array3d::Random(3);
  DerivedClass<Eigen::Array3d> o(arg);
....
}

【问题讨论】:

    标签: c++ templates partial specialization


    【解决方案1】:
    template<template<class...>class Z>
    struct template_instance_test {
      static std::false_type test(...);
      template<class...Ts>
      static std::true_type test( Z<Ts...> const* );
      template<class X>
      using tester = decltype(test( std::declval<X*>() ) );
    };
    template<template<class...>class Z, class T>
    using is_derived_from_template = typename template_instance_test<Z>::template tester<T>;
    

    我们现在可以询问某物是特定模板的实例,还是派生自特定模板的实例。

    template<class X>
    struct Base {};
    template<class X>
    struct Derived:Base<X> {};
    
    template<class T>
    struct Storage {
      T data;
    };
    template<class T, class=void>
    struct Instance:Storage<T> {
      enum {is_special = false};
    };
    template<class T>
    struct Instance<T, std::enable_if_t< is_derived_from_template<Base, T>{} > >:
      Storage<T> {
      enum { is_special = true };
    };
    
    int main() {
        Instance<int> i; (void)i;
        static_assert(!Instance<int>::is_special);
        Instance<Derived<int>> j; (void)j;
        static_assert(is_derived_from_template<Base, Base<int>>{});
        static_assert(is_derived_from_template<Base, Derived<int>>{});
        static_assert(Instance<Derived<int>>::is_special);
    }
    

    我们完成了。 Live example.

    【讨论】:

      【解决方案2】:

      如果Eigen::Array3dEigen::ArrayBase&lt;T&gt; 的别名(通过usingtypedef)对于某些T,您的代码应该可以工作。

      但我认为Eigen::Array3d 继承自Eigen::ArrayBase&lt;T&gt;。所以不是 ``Eigen::ArrayBase`,所以不匹配偏特化,所以匹配主模板。

      如果您想要一个截取从Eigen::ArrayBase 派生的所有类的特化,一种可能的解决方案是添加一个具有默认值的附加模板参数,并仅激活它T 派生自一些Eigen::ArrayBase 的特化。

      如下(注意:代码未测试)

      constexpr std::false_type isArray (...);
      
      template <typename T>
      constexpr std::true_type isArray (Eigen::ArrayBase<T> const *);
      
      template <typename T, typename = std::true_type>
      class DerivedClass : public BaseClass<T>
       {
         public:
            DerivedClass(T arg): BaseClass<T>(arg){}; 
       };
      
      template <typename T>
      class DerivedClass<T, decltype(isArray(std::declval<T*>())>
         : public DerivedClass<T>
       {
         public: 
            DerivedClass (T arg) : BaseClass<T>(arg){};
       };
      

      【讨论】:

      • 嗯,好的。我的目标是能够在这个部分专用模板中计算 Eigen::ArrayBase 的所有派生类。有没有办法解决这个问题?
      • @teflon - 我想这是可能的,但我不清楚Array3dArrayBase&lt;T&gt; 是如何相关的(类似于Array3d : ArrayBase&lt;Array3d&gt; ?)以及你需要知道的部分内容特化(ArrayBase的模板参数T?)
      • @teflon - 我已经改进了答案,添加了一个示例来展示如何为派生自 ArrayBase 的类专门化一个类(但请注意:我没有 Eigen 平台,所以我无法编译验证)。
      • 是的,ArrayBase 是 Array 的 BaseClass,而 Array3d 是 Array 我尝试从这个站点实现 ArrayBase 示例:eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html
      • 虽然在学术上,std::false_type isArray (...); 以非 pod 类型调用,但标准对它的规定非常不足。我会使用指针而不是值,这解决了这个问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-19
      • 2014-09-23
      • 2018-11-10
      相关资源
      最近更新 更多