依赖非类型模板参数和可变参数模板 [英] Dependant non-type template parameter and variadic template

查看:229
本文介绍了依赖非类型模板参数和可变参数模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想扩展 std ::使用一个名为 integer_range 的新类(它有意地在两个边界之间创建一个整数序列)来创建整数_序列 。我的实现是基于我对此问题的回答,我试图适应 std: :integer_sequence

I am trying to extend the possibilities offered by std::integer_sequence with a new class named integer_range (which obiously creates a sequence of integers between two bounds). My implementation was based of my answer to this question that I tried to adapt to std::integer_sequence:

namespace details
{
    template<typename Int, Int C, Int P, Int... N>
    struct increasing_integer_range:
        increasing_integer_range<Int, C-1, P+1, N..., P>
    {};

    template<typename Int, Int C, Int P, Int... N>
    struct decreasing_integer_range:
        decreasing_integer_range<Int, C+1, P-1, N..., P>
    {};

    template<typename Int, Int P, Int... N>
    struct increasing_integer_range<Int, 0, P, N...>:
        std::integer_sequence<Int, N...>
    {};

    template<typename Int, Int P, Int... N>
    struct decreasing_integer_range<Int, 0, P, N...>:
        std::integer_sequence<Int, N...>
    {};
}

template<typename Int, Int S, Int E,  bool Increasing=(S<E)>
struct integer_range;

template<typename Int, Int S, Int E>
struct integer_range<Int, S, E, true>:
    details::increasing_integer_range<Int, std::integral_constant<Int, E-S>, S>
{};

template<typename Int, Int S, Int E>
struct integer_range<Int, S, E, false>:
    details::decreasing_integer_range<Int, std::integral_constant<Int, E-S>, S>
{};

template<std::size_t S, std::size_t E>
using index_range = integer_range<std::size_t, S, E>;

我认为这个改变是微不足道的(添加一个 typename template参数),但这实际上在 0 的专业化中引入了一个依赖非类型参数的问题。这里是编译器错误:

I thought that the change would be trivial (adding a typename template parameter), but this actually introduces a problem with a dependant non-type parameter in the specialization for 0. Here is the compiler error:

error: type `Int` of template argument `0` depends on a template parameter

的基本问题有一些解决方案。但是,由于我使用可变参数模板,因此更难修复:此回答无法正常工作,因为我不是允许在可变参数模板之后具有默认模板参数。因此,我试图实现接受的答案中提到的修复程序,但似乎,如评论中提到的,我的编译器(g ++ 4.8.1)无法消除歧义,并认为以下两个专业化都具有同等的专业性:

The basic problem already has some solutions. However, since I use variadic templates, it becomes even harder to fix: this answer can't work because I it is not allowed to have a default template parameter after a variadic template. Therefore, I tried to implement the fix mentioned in the accepted answer but it seems that, as mentioned in the comments, my compiler (g++ 4.8.1) is unable to disambiguate and considers that the two following specialization are both equally specialized:


  • struct increasing_integer_range< Int,std :: integral_constant< Int,C>,P,N ...> ;:/* * /

  • struct increasing_integer_range< Int,std :: integral_constant< Int,0>,P,N ...> ;:/* * /

  • struct increasing_integer_range<Int, std::integral_constant<Int, C>, P, N...>: /* */
  • struct increasing_integer_range<Int, std::integral_constant<Int, 0>, P, N...>: /* */

有没有其他方法来解决这个问题?

Is there any other way to fix this problem? I am out of ideas.

推荐答案

我会简单地减少你的 integer_range std :: integer_sequence 的单个非递归调用:

I would simply reduce your integer_range to a single, non-recursive call to std::integer_sequence:

namespace details
{
    template<typename Int, typename, Int S>
    struct increasing_integer_range;

    template<typename Int, Int... N, Int S>
    struct increasing_integer_range<Int, std::integer_sequence<Int, N...>, S>
        : std::integer_sequence<Int, N+S...>
    {};

    template<typename Int, typename, Int S>
    struct decreasing_integer_range;

    template<typename Int, Int... N, Int S>
    struct decreasing_integer_range<Int, std::integer_sequence<Int, N...>, S>
        : std::integer_sequence<Int, S-N...>
    {};
}

template<typename Int, Int S, Int E,  bool Increasing=(S<E)>
struct integer_range;

template<typename Int, Int S, Int E>
struct integer_range<Int, S, E, true>:
    details::increasing_integer_range<Int, std::make_integer_sequence<Int, E-S>, S>
{};

template<typename Int, Int S, Int E>
struct integer_range<Int, S, E, false>:
    details::decreasing_integer_range<Int, std::make_integer_sequence<Int, S-E>, S>
{};

template<std::size_t S, std::size_t E>
using index_range = integer_range<std::size_t, S, E>;

我测试过:

template<std::size_t... N>
void dummy( const std::integer_sequence< std::size_t, N... >& );

int main()
{
    dummy( index_range< 2, 5 >() );
    dummy( index_range< 5, 2 >() );
}

得到预期的链接器错误:

getting the expected linker errors:

main.cpp:(.text.startup+0xa): undefined reference to `void dummy<2ul, 3ul, 4ul>(detail::integer_sequence<unsigned long, 2ul, 3ul, 4ul> const&)'
main.cpp:(.text.startup+0x14): undefined reference to `void dummy<5ul, 4ul, 3ul>(detail::integer_sequence<unsigned long, 5ul, 4ul, 3ul> const&)'

活动示例 (使用自己的实现 integer_sequence ),只需跳过第一部分)

Live example (with own implementation of integer_sequence, just skip the first part)

这篇关于依赖非类型模板参数和可变参数模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆