模板推导指南可以调用constexpr函数吗?

时间:2019-01-06 22:53:10

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

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

我以为我可以使用模板推导指南,但是看起来它并没有将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()路线的情况下进行这项工作?

3 个答案:

答案 0 :(得分:10)

您可以这样做:

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成员函数。

答案 1 :(得分:8)

  

有没有一种方法可以在不遵循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)都可以用作模板参数。

答案 2 :(得分:2)

参数/参数值不是constexpr

您可以使用可变参数模板在编译时知道大小,或者使用已知大小(std::array或C数组引用)进行键入。