C++ 避免继承类之间重复typedef
我正在我的一个库中创建一个面向元编程的小模块,它使用C++ 避免继承类之间重复typedef,c++,templates,inheritance,typedef,c++14,C++,Templates,Inheritance,Typedef,C++14,我正在我的一个库中创建一个面向元编程的小模块,它使用List类进行编译类型列表操作 我用一个空参数包专门化List,专门化某些元函数或typedef。然而,许多typedef或元函数在List和List中都有相同的实现 例如: template<typename...> struct List; template<> struct List<> { using Type = List<>; // Redundant
List
类进行编译类型列表操作
我用一个空参数包专门化List
,专门化某些元函数或typedef。然而,许多typedef或元函数在List
和List
中都有相同的实现
例如:
template<typename...> struct List;
template<> struct List<>
{
using Type = List<>; // Redundant
using Tuple = std::tuple<>; // Redundant
// ...other redundant typedefs...
template<typename TList> using Append = TList; // Non-redundant
// ...other non-redundant typedefs...
};
template<typename... Ts> struct List
{
using Type = List<Ts...>; // Redundant
using Tuple = std::tuple<Ts...>; // Redundant
// ...other redundant typedefs...
template<typename TList>
using Append = AppendImpl<Type, TList>; // Non-redundant
// ...other non-redundant typedefs...
};
模板结构列表;
模板结构列表
{
使用Type=List;//冗余
使用Tuple=std::Tuple;//冗余
//…其他冗余类型定义。。。
使用Append=TList的模板;//非冗余
//…其他非冗余类型定义。。。
};
模板结构列表
{
使用Type=List;//冗余
使用Tuple=std::Tuple;//冗余
//…其他冗余类型定义。。。
模板
使用Append=AppendImpl;//非冗余
//…其他非冗余类型定义。。。
};
如您所见,一些typedef在List
和List
之间是冗余的
我想做的与此类似:
template<typename...> struct List;
template<typename... Ts> struct ListBase
{
using Type = List<Ts...>;
using Tuple = std::tuple<Ts...>;
};
template<> struct List<> : public ListBase<>
{
template<typename TList> using Append = TList;
};
template<typename... Ts> struct List : public ListBase<Ts...>
{
template<typename TList>
using Append = AppendImpl<Type, TList>;
};
// The lines below should be valid code:
using X0 = List<>::Type;
using X1 = List<int, char, int>::Type;
using X2 = List<>::Tuple;
using X3 = List<char, char>::Tuple;
using X4 = List<>::Append<List<int, float>>;
using X5 = List<int>::Append<List<float>>;
模板结构列表;
模板结构ListBase
{
使用类型=列表;
使用Tuple=std::Tuple;
};
模板结构列表:公共ListBase
{
使用Append=TList的模板;
};
模板结构列表:公共ListBase
{
模板
使用Append=AppendImpl;
};
//以下行应为有效代码:
使用X0=List::Type;
使用X1=List::Type;
使用X2=List::Tuple;
使用X3=List::Tuple;
使用X4=List::Append;
使用X5=List::Append;
不幸的是。正如sbabbi在评论中所说,您必须使用完整的限定名来引用基类中的typedef,这对于我正在设计的列表类是不可接受的
有什么方法可以避免这种重复而不使用宏吗?换一种方法如何,将所有常见的内容保留在列表中
主模板中,然后使用单独的模板,专门用于空参数包,对于不同的部分,如追加
template<typename... Ts> struct ListAppend
{
template<typename TList>
using Append = AppendImpl<Ts..., TList>;
};
template<> struct ListAppend<>
{
template<typename TList>
using Append = TList;
};
template<typename... Ts> struct List
{
using Type = List<Ts...>;
using Tuple = std::tuple<Ts...>;
template<typename TList>
using Append = typename ListAppend<Ts...>::Append<TList>;
};
模板结构ListAppend
{
模板
使用Append=AppendImpl;
};
模板结构ListAppend
{
模板
使用Append=TList;
};
模板结构列表
{
使用类型=列表;
使用Tuple=std::Tuple;
模板
使用Append=typename ListAppend::Append;
};
现在,您只需要对不相同的部分使用专门化,并且不重复任何内容。您可以通过在列表中添加一个简单的using
语句来避免大量冗余代码。
类模板:using typename ListBase::Type代码>
对于在ListBase
中声明的每个类型,您仍然必须这样做,但是您可以在所有后续模板专门化中自由使用类型名称。下面是一个代码示例来阐明我的意思:
#include <tuple>
using namespace std;
template<typename... Ts> struct ListBase
{
using Type = ListBase<Ts...>;
using Tuple = tuple<Ts...> ;
};
template<typename... Ts> struct List : public ListBase<Ts...>
{
using typename ListBase<Ts...>::Type;
template<typename TList>
using Append = List<Type, TList>;
//more stuff using Type
};
template <> struct List<> : public ListBase<>
{
template<typename TList>
using Append = TList;
using something = Type;
};
int main() {
using X0 = List<>::Type;
using X1 = List<int, char, int>::Type;
using X2 = List<>::Tuple;
using X3 = List<char, char>::Tuple;
using X4 = List<>::Append<List<int, float>>;
using X5 = List<int>::Append<List<float>>;
return 0;
}
#包括
使用名称空间std;
模板结构ListBase
{
使用Type=ListBase;
使用Tuple=Tuple;
};
模板结构列表:公共ListBase
{
使用typename ListBase::Type;
模板
使用Append=List;
//更多使用类型的东西
};
模板结构列表:公共ListBase
{
模板
使用Append=TList;
使用某物=类型;
};
int main(){
使用X0=List::Type;
使用X1=List::Type;
使用X2=List::Tuple;
使用X3=List::Tuple;
使用X4=List::Append;
使用X5=List::Append;
返回0;
}
我希望这是解决您问题的可行办法。
你好,马塞尔·梅纳我认为你做得太多了(而且错了)
你的代码
template<typename... Ts> struct List
{
using Type = List<Ts...>; // Redundant
using Tuple = std::tuple<Ts...>; // Redundant
};
其他功能可以以类似的方式实现:
- 模板元函数的声明
- 具有可变参数和逻辑的序列的部分特殊化
- 方便使用的模板别名
可以找到一个正在运行的示例。不幸的是,typedef不会从基类传播到派生类。
从技术上讲,它们会传播,如果名称是依赖的,您只需使用完整的限定名来引用基类中的typedef。冗余在哪里?您正在使用不同的类型…您对模板结构列表的定义实际上很好:问题是在依赖基类中查找名称ListBase
不依赖,因此显式(完全)专门化List
@sbabbi没有问题,我不确定“完全限定名”应该是什么意思;使用注入的类名使名称依赖就足够了。例如,typename List::template AppendImpl
在主模板List
@DanDan中:Type
和Tuple
的实现不需要写两次,因为变量列表为空的变量模板实现仍然会返回正确答案(List
和std::tuple
)。Append
根据列表是否为空,具有不同的行为。
template<typename List>
struct to_tuple_impl;
template<typename... Ts>
struct to_tuple_impl<List<Ts...>> {
using Type = std::tuple<Ts...>;
};
template<typename List>
using to_tuple = typename to_tuple_impl<List>::Type;