【问题标题】:Exception if terminating function reached in variadic template unpacking如果在可变参数模板解包中达到终止函数,则异常
【发布时间】:2014-03-09 13:27:18
【问题描述】:

所以我在玩模板和 constexpr,特别是可变参数模板,我做了以下函数:

template <typename T>
constexpr T get_argument(size_t index)
{
  return T();
};

template <typename T, T arg, T... args>
constexpr T get_argument(size_t index)
{
  return index ? get_argument<T,args...>(index-1) : arg;
}

这里的终止函数目前是一个虚拟占位符。所以这个函数有效,但如果超出范围则返回 0,我想要它做的是崩溃......但它需要 2 种失败模式。 get_argument 可以在编译时调用,我希望索引超出范围以导致编译器错误。或者它可以在运行时调用,我希望它抛出运行时错误......

我也有这个选项:

template <typename T>
constexpr T get_argument(size_t index)
{
  return false ? T() : throw std::out_of_range("Index out of argument range");
}

template <typename T, T arg, T... args>
constexpr T get_argument(size_t index)
{
  return index ?
        (count_args<T,args...>() ?
           get_argument<T,args...>(index-1) :
           throw std::out_of_range("Index out of argument range")) :
        arg;
}

但是 1)我不喜欢语法(总是错误的条件,加上模糊地检查两次以使输出意味着什么),以及 2)错误很混乱:

test.hpp:32:69: error: expression '<throw-expression>' is not a constant-expression
            throw std::out_of_range("Index out of argument range")) :

谁有更好的方法?

【问题讨论】:

  • 你有没有想过返回一个指针(超出范围时为空)?
  • @MatthieuM。在有效的情况下它会指向什么? Args 仅作为模板参数存在...
  • 啊,对了,不幸的是没有std::option...我想你可以自己包装它(使用布尔值和默认T创建你自己的简单option&lt;T&gt;)。

标签: c++ c++11 variadic-templates constexpr


【解决方案1】:

以下可能会有所帮助(仅一项检查):

template <typename T, T ... Ts>
constexpr std::array<T, sizeof...(Ts)> getArray()
{
    return {{Ts...}};
}

template <typename T, T ... Ts>
constexpr T get_argument(size_t index)
{
  return index < sizeof...(Ts) ?
    const_cast<const std::array<T, sizeof...(Ts)>&&>(getArray<T, Ts...>())[index] :
    throw std::out_of_range("Index out of argument range");;
}

C++14 可能会有所帮助,可能有几个语句,如:

  • 局部变量(不需要这个const_cast
  • assert(可能除了throw)。

【讨论】:

  • 有趣的解决方案...为什么需要 const_cast?
  • 临时数组不是 const 且operator[] 是 constexpr 仅适用于 const 对象。
  • 嗯,有道理(我 +1,因为是的)。下一个问题:在运行时调用 this 的情况下,我的方法可以递归内联(如果编译器支持),它(可能,可能,如果编译器魔法)减少到一个常量值返回......这会修复必须为 std::array 进行堆分配吗? (我可能只需要检查程序集才能得到这个答案,但如果你知道那会很酷)
  • (如果 T 没有默认构造函数,这也解决了问题)
  • array::operator[] 在 C++11 中不是 constexpryou need to roll your own。令人惊讶的是,代码实际上变得更简单了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-20
  • 2023-03-14
  • 2012-06-04
  • 1970-01-01
相关资源
最近更新 更多