简体   繁体   English

部分类模板专业化c ++ 11

[英]Partial class template specialization c++11

I am trying to compile the below code, but I am getting the error: 我正在尝试编译以下代码,但我收到错误:

wrong number of template arguments 错误的模板参数数量

template<int start, int end, int step>
struct range{};

template<int start, int end>
struct range<start, end, 1>{};

template<int end>
struct range<0, end, 1>{};

int main() {
    auto r1 = range<0, 5, 2>{};
    auto r2 = range<5, 15>{}; //error: wrong number of template arguments
    auto r3 = range<10>{}; //error: wrong number of template arguments
}

How can I create partial template class object? 如何创建部分模板类对象?

You need to specify all the template arguments according to the primary template's declaration, then which one selected will be determined according to the template arguments. 您需要根据主模板的声明指定所有模板参数,然后根据模板参数确定选择的参数。

auto r1 = range<0, 5, 2>{};  // the primary template
auto r2 = range<5, 15, 1>{}; // the 1st partial specified template
auto r3 = range<0, 10, 1>{}; // the 2nd partial specified template

If you want to specify fewer template arguments you might want default template arguments : 如果要指定较少的模板参数,则可能需要默认模板参数

template<int end, int start = 0, int step = 1>
struct range{};

auto r1 = range<5, 0, 2>{}; // end->5, start->0, step->2
auto r2 = range<15, 5>{};   // end->15, start->5, step->1
auto r3 = range<10>{};      // end->10, start->0, step->1

Note that I changed the order of the template parameters, because if the default argument is specified for a template parameter, each subsequent template parameter must have a default argument too. 请注意,我更改了模板参数的顺序,因为如果为模板参数指定了默认参数,则每个后续模板参数也必须具有默认参数。

If you want the ability to specify start before end , but also to have a default argument for start you could do something like this: 如果你想要能够指定start before end ,还有一个默认参数用于start你可以这样做:

template <int... Args>
struct range {
    static_assert(sizeof...(Args) > 0 && sizeof...(Args) <= 3, 
                  "Must pass 1-3 args");

    using ArgPack = std::tuple<std::integral_constant<int, Args>...>;

    template <int Size, typename Then, typename Else>
    using select_value = typename std::conditional_t<
         (sizeof...(Args) > Size), Then, Else
    >::type;

    static constexpr int start = select_value<1,
        std::tuple_element<0, ArgPack>, std::integral_constant<int,0>
    >::value;

    static constexpr int end = select_value<1, 
        std::tuple_element<1, ArgPack>, std::tuple_element<0, ArgPack>
    >::value;

    static constexpr int step = select_value<2, 
        std::tuple_element<2, ArgPack>, std::integral_constant<int,1>
    >::value;
};

This has exactly the usage which you desire, like this: 这正是您想要的用法,如下所示:

int main()
{
   using a = range<1,1,2>;
   static_assert(a::start == 1 && a::end == 1 && a::step == 2, "wat");

   using b = range<1,1>;
   static_assert(b::start == 1 && b::end == 1 && b::step == 1, "wat");

   using c = range<3>;
   static_assert(c::start == 0 && c::end == 3 && c::step == 1, "wat");
}

Live Demo 现场演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM