使用CRTP和多重继承消除冗余

时间:2015-06-19 14:39:02

标签: c++ multiple-inheritance c++03 crtp

这个问题适用于C ++ 03,而不是C ++ 11。

我有一个案例,我正在使用具有多重继承的CRTP,我很想知道是否有一种方法可以删除在下面指定B类型时创建的冗余。

#include "boost/typeof/typeof.hpp"
#include "boost/units/detail/utility.hpp"
#include <iostream>
#include <string>

struct One{};
struct Two{};

template<typename T>
struct Type
{
   static std::string name(void)
   {
      return boost::units::detail::demangle(typeid(T).name());
   }
};

template<typename T1,
         typename T2>
struct A
{
   typedef A<T1, T2> Self;

   A()
   {
      std::cout << Type<Self>::name() << std::endl;
   }
};

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, B<T1, T2, T3> >, // The B<T1, T2, T3> here is redundant
           public A<Two, B<T1, T2, T3> >
{
   typedef B<T1, T2, T3> Self;

   B()
   {
      std::cout << Type<Self>::name() << std::endl;
   }
};

int main(int argc, char* argv[])
{
   B<int, int, int> t;
   return 0;
}

Coliru

上查看

B的模板参数数量增加,模板参数本身很复杂,BA继承多次时,问题就会恶化。我想尽量减少B模板参数的重复。具体来说,我正在寻找一种方法来访问typedef B<T1, T2, T3> Self的继承列表中的B,或者this的一些等效编译时版本。

我不能:

  • 使用转发声明为B B创建一个typedef,因为我无法访问模板参数
  • 在继承定义的中创建typedef ,因为语法不允许
  • 从类中访问typedef,因为它还不存在

如下所示(其中没有一个不是有效代码,但显示我正在寻找的效果):

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, Self>, // Cannot access the typedef yet
           public A<Two, Self>
{
   typedef B<T1, T2, T3> Self;
};

template<typename T1,
         typename T2,
         typename T3>
struct B : typedef B<T1, T2, T3> Self, // Invalid syntax
           public A<One, Self>, 
           public A<Two, Self>
{

};

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, B>, // I wish this would work
           public A<Two, B>
{

};

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, BOOST_TYPEOF(*this)>, // lol
           public A<Two, BOOST_TYPEOF(*this)>
{

};

有没有办法访问this的编译时版本?

1 个答案:

答案 0 :(得分:0)

问题:

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, B>, // I wish this would work
           public A<Two, B>
{

};

是您的template <typename T1, typename T2> struct A要求的 使用T2 类型进行实例化,而您希望可以执行此操作 用T2 模板来实例化它,即 template<typename, typename,typename> struct B

如果A的定义在你自己的控制之下,那么也许 - 尽管可能不是 - 解决方案 是使A的定义符合您的愿望:

#include "boost/typeof/typeof.hpp"
#include "boost/units/detail/utility.hpp"
#include <iostream>
#include <string>

struct One{};
struct Two{};

template<typename T>
struct Type
{
   static std::string name(void)
   {
      return boost::units::detail::demangle(typeid(T).name());
   }
};

template<typename T1,
         template<typename, typename, typename> class T2
>
struct A
{

   A()
   {
      std::cout << Type<A>::name() << std::endl;
   }
};


template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, B >,
           public A<Two, B >
{
   B()
   {
      std::cout << Type<B>::name() << std::endl;
   }
};


int main(int argc, char* argv[])
{
   B<int, int, int> t;
   return 0;
}

此程序打印:

A<One, B>
A<Two, B>
B<int, int, int>

此解决方案的价格限制了其中的类 A可以为实例化模板的人提供CRTP基础,例如 B,正好有三个typename个参数。

也许你很幸运,这种限制不会阻碍任何其他限制 祝你有。但是如果你还需要A来提供CRTP基础 对于实例化一些不具有三个模板的类的类 typename参数,然后咬人。

前提是您需要A提供CRTP的所有类 base是仅具有typename个参数的模板的实例化, 并且最多只有N个,那么你仍然可以拥有一个C ++ 03解决方案 同样的精神:

根据架构定义A

template<typename T1,
         template<typename /*1*/,.... typename /*N*/> class T2
>
struct A { ... };

对于Y作为CRTP基础的每个模板A,您提供 准确N参数,使用&#34;填充&#34;默认的参数 必要时void。例如,如果N == 3:

#include "boost/typeof/typeof.hpp"
#include "boost/units/detail/utility.hpp"
#include <iostream>
#include <string>

struct One{};
struct Two{};

template<typename T>
struct Type
{
   static std::string name(void)
   {
      return boost::units::detail::demangle(typeid(T).name());
   }
};

template<typename T1,
         template<typename, typename, typename> class T2
>
struct A
{

   A()
   {
      std::cout << Type<A>::name() << std::endl;
   }
};


template<typename T1, typename T2 = void, typename T3 = void>
struct B : public A<One, B >,
           public A<Two, B >
{
   B()
   {
      std::cout << Type<B>::name() << std::endl;
   }
};

template<typename T1, typename T2, typename T3 = void>
struct C : public A<One, C >,
           public A<Two, C >
{
   C()
   {
      std::cout << Type<C>::name() << std::endl;
   }
};

template<typename T1, typename T2, typename T3>
struct D : public A<One, D >,
           public A<Two, D >
{
   D()
   {
      std::cout << Type<D>::name() << std::endl;
   }
};



int main(int argc, char* argv[])
{
   B<int> b;
   C<int,int> c;
   D<int,int,int> d;
   return 0;
}

此程序打印:

A<One, B>
A<Two, B>
B<int, void, void>
A<One, C>
A<Two, C>
C<int, int, void>
A<One, D>
A<Two, D>
D<int, int, int>

是的,更通用的解决方案可以为您提供不同类型的&#34;冗余&#34;,in 那些多余的默认模板参数的形式。但是你 可能会觉得它不那么令人厌烦。

(gcc 5.1 / clang 3.6,C ++ 03)