c++ - 尝试传递一个 constexpr lambda 并使用它来显式指定返回类型

标签 c++ lambda c++17 constexpr stdarray

我想使用一个函数并传递一个 constexpr lambda .但是,如果我通过 auto 推导类型,它只会编译成功。 .通过 -> std::array<event, l()> 明确给出类型似乎失败了(第一次)。这是为什么?

template <typename Lambda_T>
constexpr static auto foo(Lambda_T l) -> std::array<event, l()> {
    return {};
} // error

template <typename Lambda_T>
constexpr static auto foo(Lambda_T l) {
    return std::array<event, (l())>{};
} // OK

template <typename Lambda_T>
constexpr static auto foo(Lambda_T l) -> decltype(l()) { return {}; }
// OK

请注意,lambda 返回 size_t .

在没有调用的情况下 gcc 错误(clang 接受它):

prog.cc:9:63: error: template argument 2 is invalid
    9 | constexpr static auto foo(Lambda_T l) -> std::array<event, l()>
      |                                                               ^
prog.cc:9:63: error: template argument 2 is invalid
prog.cc:9:63: error: template argument 2 is invalid
prog.cc:9:63: error: template argument 2 is invalid
prog.cc:9:42: error: invalid template-id
    9 | constexpr static auto foo(Lambda_T l) -> std::array<event, l()>
      |                                          ^~~
prog.cc:9:61: error: use of parameter outside function body before '(' token
    9 | constexpr static auto foo(Lambda_T l) -> std::array<event, l()>
  |                                                             ^
prog.cc:9:23: error: deduced class type 'array' in function return type
    9 | constexpr static auto foo(Lambda_T l) -> std::array<event, l()>
  |                       ^~~
In file included from prog.cc:4:
/opt/wandbox/gcc-head/include/c++/9.0.1/array:94:12: note: 
'template<class _Tp, long unsigned int _Nm> struct std::array' declared here
   94 |     struct array
      |            ^~~~~
prog.cc: In function 'int main()':
prog.cc:14:5: error: 'foo' was not declared in this scope
   14 |     foo([]() {return 3; });
      |     ^~~

最佳答案

constexpr 函数的参数本身不是 constexpr 对象 - 因此您不能在常量表达式中使用它们。你的两个例子都返回 array s 格式错误,因为没有对它们的有效调用。

要理解原因,请考虑这个无意义的示例:

struct Z { int i; constexpr int operator()() const { return i; }; };

template <int V> struct X { };
template <typename F> constexpr auto foo(F f) -> X<f()> { return {}; }

constexpr auto a = foo(Z{2});
constexpr auto b = foo(Z{3});

Z有一个 constexpr调用运营商,这是合式的:

constexpr auto c = Z{3}();
static_assert(c == 3);

但如果允许更早的用法,我们将调用两次 foo<Z>那将不得不返回不同的类型。这只有在实际值 f 时才能飞是模板参数。


请注意,clang 编译声明本身并不是编译器错误。这是一类格式错误的情况,不需要诊断。

关于c++ - 尝试传递一个 constexpr lambda 并使用它来显式指定返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54353463/

相关文章:

c++ - 在 MFC 中更改 listcntrl 的方向时出错

c++ - 为什么启用分析后我的程序运行得更快?

lambda - Java8,将带有条件的for循环转换为lambda

c++ - 使用宏替换具有细微差异的重复代码块

c++ - constexpr if with initializer 由标准保证吗? 'constexpr(constexpr auto x = f(); x) { }'

c++ - std::exception_ptr 的大小限制

c++ - 在前向声明中自动推导返回类型并与旧函数语法混合

c++ - 无法将 std::bind 与可变模板参数一起使用

c++ - C++ lambda 捕获参数名称等局部变量

c++ - 对具有继承的结构使用初始化列表