模板方法,其参数个数为实例化而固定,但可通过模板参数变量

时间:2015-10-02 17:55:40

标签: c++ templates

我想使用整数模板参数为模板类定义一个函数,以便函数参数的数量取决于模板参数。这是一个例子:

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函数,但我发现基本上重复相同代码的做法是非C ++ - ish。此外,我不应该专门针对int模板参数的每个可能值。

是否可以实现Point<Coord,dim>::Set()函数,该函数可以使用dim类型的Coord个参数,而无需为dim的每个值编写特化代码?

1 个答案:

答案 0 :(得分:10)

你可以使用Boost.Hana用于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>;