c++ - 依赖非类型模板参数和可变参数模板

标签 c++ templates template-specialization c++14 indices

我正在尝试扩展 std::integer_sequence 提供的可能性有一个名为 integer_range 的新类(这在两个边界之间创建了一个整数序列)。我的实现基于我对 this question 的回答我试图适应 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 模板参数),但这实际上在 0 的特化中引入了依赖非类型参数的问题。 .这是编译器错误:

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

基本问题already has一些解决方案。但是,由于我使用可变参数模板,修复起来就更难了:this answer无法工作,因为我不允许在可变参数模板后使用默认模板参数。因此,我尝试实现 the accepted answer 中提到的修复但似乎,如评论中所述,我的编译器 (g++ 4.8.1) 无法消除歧义,并认为以下两个特化都同样特化:

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

有没有其他方法可以解决这个问题?我没主意了。

最佳答案

我会简单地将您的 integer_range 缩减为对 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 >() );
}

得到预期的链接器错误:

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&)'

Live example (自己实现了integer_sequence,直接跳过第一部分)

关于c++ - 依赖非类型模板参数和可变参数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23228894/

相关文章:

c++ - 如何使用 FILE* 写入内存缓冲区?

c++ - 具有跨 DLL/SO 使用的静态数据成员的模板类

c++ - 编译器看不到模板特化?

c++ - std 集合上的 CPPUNIT_ASSERT_EQUAL

c++ - 代码输出说明

c++ - 错误 : two or more data types in declaration of main?

c++ - 是否可以从 COFF 库文件 (.lib) 中去除调试信息?

c++ - 如何从客户端代码中隐藏模板化的非成员函数?

c++ - 如何定义仅接受具有已定义 API 的类型的模板函数

c++ - VS2017模板特化报错cannot convert from 'Class *(__cdecl *)(Args...)' to 'Class *(__cdecl *)(Args...)'