Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 避免继承类之间重复typedef_C++_Templates_Inheritance_Typedef_C++14 - Fatal编程技术网

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;