【问题标题】:Can template deduction guides call constexpr functions?模板推导指南可以调用 constexpr 函数吗?
【发布时间】:2019-06-01 15:52:08
【问题描述】:

我有自己的固定大小的数组类型,我想从std::initializer_list 构造为constexpr,而不必显式定义大小模板参数。

我以为我可以使用模板推导指南,但它似乎没有将 std::initializer_list::size() 视为它的 constexpr 函数。

下面是一个尝试为std::array做推演指南的例子(和我的类型差不多,也有同样的问题):

namespace std
{
    template<typename T> array(initializer_list<T> initialiserList) -> array<T, initialiserList.size()>;
}
static constexpr std::array myArray = {1,2,3};
static constexpr std::array myArray2 = {{1,2,3}};

我在 MSVC 和 Clang 上试过,都给出了大致相同的错误: myArray 有一个错误,抱怨函数的参数太多。 myArray2 表示“替换失败 [with T = int]:非类型模板参数不是常量表达式”

我尝试将 constexpr 放在推导指南或函数参数的前面,但似乎都不允许,因此即使在 constexpr 上下文中应该可以正常工作,推导指南似乎也是无效的。

有没有办法在不走make_array() 路线的情况下完成这项工作?

【问题讨论】:

    标签: c++ c++17 constexpr template-argument-deduction


    【解决方案1】:

    你可以这样做:

    template <class T, class... U>
    array(T, U...) -> array<T, 1 + sizeof...(U)>;
    

    问题不在于你不能在演绎指南中调用constexpr 函数。你可以。这个例子很荒谬,但很有效:

    constexpr size_t plus_one(size_t i) { return i + 1; }
    
    template <class T, class... U>
    array(T, U...) -> array<T, plus_one(sizeof...(U))>;
    

    问题在于函数参数不是constexpr 对象,因此如果这些成员函数读取某种本地状态,则不能在它们上调用constexpr 成员函数。

    【讨论】:

      【解决方案2】:

      有没有办法在不走make_array() 路线的情况下完成这项工作?

      您为什么不尝试以下扣除指南?

      template <typename T, std::size_t N>
      array(T const (&)[N]) -> array<T, N>;
      

      这样,myArray2 = {{1,2,3}} 中的参数不会被解释为std::initializer_list(不能将其视为constexpr,因此size() 不能用于模板参数)但是作为 C 样式的数组。

      因此可以推断,作为模板参数,类型和大小(TN)以及大小(N)都可以用作模板参数。

      【讨论】:

        【解决方案3】:

        参数/参数值不是constexpr

        您可以在编译时使用可变参数模板来知道大小,或者使用知道大小的类型(std::array 或 C 数组引用)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多