模板方法,其参数数量为实例化固定,但因模板参数而异

Template method with number of arguments fixed for instantiation but variable by template parameter

本文关键字:参数 实例化 数数 模板方法      更新时间:2023-10-16

我想为模板类定义一个带有整型模板形参的函数,以便函数实参的数量取决于模板形参。下面是一个例子:

template< class Coord, int dim >
class Point {
    Coord mCoords[ dim ];
public:
    void Set( /* I want exactly dim Coord arguments here. */ );
};

我想编译以下代码:

Point<double,2> pt2d;
pt2d.Set( 25, 32 );
Point<double,3> pt3d;
pt3d.Set( 25, 32, 100 );

和下面的代码失败:

Point<double,2> pt2d;
pt2d.Set( 25, 32, 100 );  // Too many arguments
Point<double,3> pt3d;
pt3d.Set( 25, 32 );       // Too few arguments

现在,我可以在较小的维度上手动专门化Point以具有不相关的Set函数,但我发现基本上重复相同代码的做法是un- c++ -ish。此外,我不需要对int模板形参的每个可能值都进行专门化。

是否有可能实现Point<Coord,dim>::Set()函数,该函数将完全采用Coord类型的dim参数,而无需为dim的每个值编写专门化代码?

您可以使用Boost的技巧。getNth:

template <typename Coord, int dim, typename = std::make_index_sequence<dim>>
struct Point;
template <typename Coord, int dim, size_t... Ignore>
struct Point<Coord, dim, std::index_sequence<Ignore...>>
{
    void Set(decltype(Ignore, Coord{})... args)
    {
        // ...
    }
};

一个较长的版本,隐藏了Ignore的丑陋(并适用于非默认可构造的Coord s…)将添加一些元编程样板:

template <typename... > struct typelist { };
template <int N, typename T, typename = std::make_index_sequence<N>>
struct repeat;
template <int N, typename T>
using repeat_t = typename repeat<N, T>::type;
template <int N, typename T, size_t... Idx>
struct repeat<N, T, std::index_sequence<Idx...>>
{
    template <size_t >
    struct makeT { using type = T; };
    using type = typelist<typename makeT<Idx>::type...>;
};

然后专门研究repeat_t。并将其隐藏在一个命名空间中,这样用户就不会把它弄乱:

namespace details {
    template <typename Coord, int dim, typename = repeat_t<dim, Coord>>
    struct Point;
    template <typename Coord, int dim, typename... dimCoords>
    struct Point<Coord, dim, typelist<dimCoords...>>
    {
        void Set(dimCoords... args)
        {
        }
    };
}
template <typename Coord, int dim>
using Point = details::Point<Coord, dim>;