gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:49:57 24 4
gpt4 key购买 nike

这个问题是针对 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 的模板参数数量增加时,问题会变得更糟增加,当模板参数本身很复杂,并且当B继承自 A更多次。我想尽量减少 B 的重复的模板参数。具体来说,我正在寻找一种方法来访问 typedef B<T1, T2, T3> SelfB 的继承列表中,或 this 的一些等效编译时版本.

我不能:

  • B做一个typedef以上B使用前向声明,因为我无权访问模板参数
  • 在继承定义的内部创建一个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 的编译时版本? ?

最佳答案

问题在于:

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参数,然后它咬。

前提是您需要的所有类(class) A提供 CRTPbase 是只有 typename 的模板实例参数,最多有 N其中,那么您仍然可以在同样的精神:

你定义A根据架构:

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

并且对于每个模板Y为此 A是做一个CRTP基础,你提供正是 N参数,使用默认为的“填充”参数 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>

是的,更通用的解决方案会让你陷入一种不同的“冗余”,在那些多余的默认模板参数的形式。但是你可能会觉得它不那么令人讨厌。

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

关于c++ - 使用 CRTP 和多重继承消除冗余,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30940909/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com