是否可以在类模板演绎指南中使用折叠表达式?

Is it possible to use fold expression in class template deduction guide?

提问人:Nima Ghorab 提问时间:4/3/2022 更新时间:4/3/2022 访问量:168

问:

我做了一个简单的测试,如下所示:

#include <iostream>

template <typename T, std::size_t N, std::size_t D> struct MyArray {
    template <typename First, typename ... Rest> MyArray(First, Rest...);
    int dimension[N];
    T m_array[D];
};

template <typename First, typename... Rest> MyArray(First first, Rest... values)
    -> MyArray<First, 1 + sizeof...(values), (values * ...)>;

int main()
{
    MyArray arr{3, 2, 3};
    return 0;
}

编译器对此表示不满:

main.cpp:14:13: No viable constructor or deduction guide for deduction of template arguments of 'MyArray'
main.cpp:4:50: candidate template ignored: couldn't infer template argument 'T'
main.cpp:9:45: candidate template ignored: substitution failure [with First = int, Rest = <int, int>]: non-type template argument is not a constant expression
main.cpp:3:60: candidate function template not viable: requires 1 argument, but 3 were provided

如果我用 18 替换,一切都按预期工作。 有没有办法从 C++ 演绎指南中的折叠表达式中受益?(values * ...)

C++ 模板 演绎指南

评论


答:

3赞 user17732522 4/3/2022 #1

不能在常量表达式中使用函数参数的值,尤其不能在模板参数中使用函数参数的值。

如果要对不同的值以不同的方式推断类型,则需要确保类型也因值而异。

例:

#include<type_traits>

template<auto V>
constexpr auto constant = std::integral_constant<decltype(V), V>{};

//...

MyArray arr{3, constant<2>, constant<3>};

据我所知,这应该与您的演绎指南一起使用,尽管 GCC 和 MSVC 似乎都对这段代码有问题,这在我看来就像是错误。

std::integral_constant隐式转换为其模板参数中的值。此转换不需要访问该类型的给定时刻的值,因此应该没问题。(values * ...)

sizeof...(values)总是没问题的,因为它根本不会访问。它只是扩展到包中的物品数量。values

GCC 声明不包含未扩展的包,这对我来说似乎是错误的。MSVC 有一个内部编译器错误,这绝对是一个错误。但 Clang 接受了这种变化。(values * ...)