C++ 使用C++;模板元编程

C++ 使用C++;模板元编程,c++,c++11,c++14,variadic-templates,template-meta-programming,C++,C++11,C++14,Variadic Templates,Template Meta Programming,如何编写一个模板meta_集,使meta_集::type`对于Ts的所有排列都是相同的 换句话说,只要参数列表是相同的,无论顺序如何,我们都希望使用相同的meta_set::type,也就是说,当作为一个集合(或多集合,如果更容易的话) 比如说, std::is_same< meta_set<int,double,string>::type, meta_set<double,string,int>::type >::value == true std::is

如何编写一个模板
meta_集
,使meta_集::type`对于Ts的所有排列都是相同的

换句话说,只要参数列表是相同的,无论顺序如何,我们都希望使用相同的
meta_set::type
,也就是说,当作为一个集合(或多集合,如果更容易的话)

比如说,

std::is_same< meta_set<int,double,string>::type, meta_set<double,string,int>::type  >::value == true
std::is_same< meta_set<int,double,string>::type, meta_set<double,string,bool>::type  >::value == false
std::is_same::value==true
std::is_same::value==false
当您希望每个模板参数集都有一个模板实例化时,这可能会很方便


注意:这不是一个家庭作业,而是我在工作中处理大量模板代码时感到好奇的事情。我不是元编程专家,所以我想也许人们可以分享他们的知识

规范化表示一组类型的唯一可行方法是使用排序列表(或可以转换为排序列表的东西,例如二进制搜索树)。但是C++中没有类型的自然编译时间排序,所以没有什么排序。 <> > C++应该要求<代码> STD::Type:No::在 >代码> CONTXPROP>代码>,或定义一个具有类似功能的模板,比如<>代码> STD::在之前,它将创建类型之间的全局静态排序,从而可以创建规范有序的列表。遗憾的是,情况并非如此


由于缺少编译器支持的排序,程序员必须为每一对可能的类型定义自己的
is_pre
,这当然不是每一对类型都可能做到的,但只适用于某些有限的已知预先集。

规范化表示一组类型的唯一可行方法是使用排序列表(或者可以转换成排序列表的东西,例如二进制搜索树),但是C++中没有类型的自然编译时间排序,所以没有什么排序。

<> > C++应该要求<代码> STD::Type:No>:在 >代码> COSTEXPRO< /COD>,或者定义一个具有类似功能的模板,例如<>代码> STD::在之前,它将创建类型之间的全局静态排序,这将使得创建规范有序列表成为可能。
由于缺少编译器支持的排序,程序员必须为每一对可能的类型定义自己的
is_\u,这当然不可能对每一对类型都这样,但只能对一些有限的已知预先设置进行定义。

无法在编译时对所有类型进行全局排序;访问
typeid(T)之类的内容(typeid(U))
不是
constepr
。因此不能将两个任意
meta\U集
meta\U集
设置为同一类型,因为不能排序

如果类型不相同,则无法修改
std::is_same
的行为以返回true。任何试图这样做的代码(例如通过专门化
std::is_same
)都将违反
std::is_same
的要求,这将导致程序格式错误,无需诊断

如果将类型集限制为所有类型的某个子集,则可以执行此操作。最简单的方法是使用集中列表:

template<class...T>
struct types_t {};

using global_order = types_t<int, double, std::string>;
一旦写下:

template<class...Ts>
using meta_set = typename type_sorter< types_t<Ts...> >::type;

这就像是
std::is_same
,除非fed
meta_集
s会检查它们是否具有相同的内容,而不是寻找严格的类型相等。但是,您的评论提到这不是您的实际问题,而是您正在谈论将
meta_集
参数传递到不同的模板d希望它们按规范顺序排列。

在编译时无法全局排序所有类型;访问诸如
typeid(T)之类的东西。在(typeid(U))
之前,不可将两个任意的
meta_set
meta设置为同一类型,因为您无法排序

如果类型不相同,则无法修改
std::is_same
的行为以返回true。任何试图这样做的代码(例如通过专门化
std::is_same
)都将违反
std::is_same
的要求,这将导致程序格式错误,无需诊断

如果将类型集限制为所有类型的某个子集,则可以执行此操作。最简单的方法是使用集中列表:

template<class...T>
struct types_t {};

using global_order = types_t<int, double, std::string>;
一旦写好:

template<class...Ts>
using meta_set = typename type_sorter< types_t<Ts...> >::type;

这就像是
std::is_same
,除非fed
meta_集
s会检查它们是否具有相同的内容,而不是寻找严格的类型相等。但是,您的评论提到这不是您的实际问题,而是您正在谈论将
meta_集
参数传递到不同的模板我的想法不是对类型进行排序,而是检查第一个元集中的类型是否出现在第二个元集中

template <typename... Args>
struct TypeList;

template <typename Head, typename... Tail>
struct TypeList<Head, Tail...>
{
    using TailList = TypeList<Tail...>;
    using HeadType = Head;

    static_assert(!TailList::template contains<Head>(), "Types must be unique");

    static constexpr int size()
    {
        return 1 + TailList::size();
    }

    template <typename Type>
    static constexpr bool contains()
    {
        return std::is_same<Head, Type>::value || TailList::template contains<Type>();
    }
};

template<>
struct TypeList<>
{
    static constexpr int size()
    {
        return 0;
    }

    template <typename Type>
    static constexpr bool contains()
    {
        return false;
    }
};


template <typename ListLhs, typename ListRhs>
struct IsSame
{
    static constexpr bool value()
    {
        return ListLhs::size() == ListRhs::size() && valueImpl();
    }

    static constexpr bool valueImpl()
    {
        return ListLhs::template contains<typename ListRhs::HeadType>() &&
               IsSame<ListLhs,typename ListRhs::TailList>::valueImpl();
    }
};

template <typename ListLhs>
struct IsSame<ListLhs, TypeList<>>
{
    static constexpr bool value()
    {
        return false;
    }

    static constexpr bool valueImpl()
    {
        return true;
    }
};

template <>
struct IsSame<TypeList<>, TypeList<>>
{
    static constexpr bool value()
    {
        return true;
    }

    static constexpr bool valueImpl()
    {
        return false;
    }
};

struct MyStruct{};

using Types = TypeList<int, bool, char, MyStruct, double>;
using TypesSame = TypeList<int, MyStruct, bool, char, double>;
using LessTypes = TypeList<int, bool, char>;
using EmptyTypes = TypeList<>;

static_assert(IsSame<Types, TypesSame>::value(), "Underlying types should be the same");
static_assert(!IsSame<Types, LessTypes>::value(), "Less types");
static_assert(!IsSame<Types, EmptyTypes>::value(), "Not the same as Empty");
static_assert(IsSame<EmptyTypes, EmptyTypes>::value(), "Empty types");
模板
结构类型表;
模板
结构类型表
{
使用TailList=类型列表;
使用头型=头;
静态断言(!TailList::template contains(),“类型必须唯一”);
静态constexpr int size()
{
返回1+TailList::size();
}
模板
静态constexpr bool contains()
{
return std::is|u same::value | | TailList::template contains();
}
};
模板
结构类型表
{
静态constexpr int size()
{
返回0;
}
模板
静态constexpr bool contains()
{
返回false;
}
};
模板
结构名称
{
静态constexpr布尔值()
{
返回ListLhs::size()==ListRhs::size()&&valueImpl();
}
静态constexpr bool valueImpl()
{
return ListLhs::template contains()&&
IsName::valueImpl();
}
};
模板
结构名称
{
静态constexpr布尔值()
{
返回false;
}