【问题标题】:Template method with number of arguments fixed for instantiation but variable by template parameter具有固定实例化参数数量但由模板参数可变的模板方法
【发布时间】:2015-10-02 17:55:39
【问题描述】:

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

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++ 风格。此外,我不必专门针对 int 模板参数的每个可能值。

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

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    您可以使用 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 丑陋的更长版本(并且适用于非默认构造的Coords...)将添加一些元编程样板:

    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>;
    

    【讨论】:

    • 可以从index_sequence 推导出ints 吗?
    • @PiotrSkotnicki 是的。不过还是改成了size_t
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 2014-09-08
    • 1970-01-01
    • 2014-06-30
    相关资源
    最近更新 更多