是否在未评估的上下文中实例化模板/ lambda是否未指定?

Jar*_*d42 12 c++ lambda templates instantiation language-lawyer

我尝试以下代码检查模板是否在未评估的上下文中实例化:

#include "foo.h"

template <typename T = int>
constexpr auto f(int)
// from declaration, foo(std::declval<T>()) is allowed.
// Even if definition would produce errors if instantiated
-> decltype(foo(std::declval<T>()), void(), 42)
{
    return 42;
}
static_assert(f(0) == 42);
Run Code Online (Sandbox Code Playgroud)

foo作为模板功能:(没有错误)

template <typename ...Ts>
void foo(Ts... args)
{
    static_assert(sizeof...(Ts) == 42, "!");
    ((args += ""), ...);
}
Run Code Online (Sandbox Code Playgroud)

演示版

foo定期函子:(没有错误)

struct Foo
{
    template <typename ...Ts>
    void operator ()(Ts... args) const
    {
        static_assert(sizeof...(args) == 42, "!");
        ((args += ""), ...);
    }
} foo;
Run Code Online (Sandbox Code Playgroud)

演示版

但是foo作为lambda :(错误)

auto foo = [](auto... args)
{
    static_assert(sizeof...(args) == 42, "!"); // Triggers
    ((args += ""), ...);                       // spotted as invalid: int += const char*
};
Run Code Online (Sandbox Code Playgroud)

演示版

operator()实例化lamdba 是否正常?

gcc / clang具有相同的行为。

Rak*_*111 15

lambda情况实际上不同于其他情况!您无需为lambda指定返回类型,因此可以推论得出。为了进行推导,必须实例化lambda。

对于函数对象,情况并非如此,因为您在此处将返回类型指定为void。更改lambda以返回void以避免扣除,会使gcc / clang满意。:)

auto foo = [](auto... args) -> void // <---
{
    static_assert(sizeof...(args) == 42, "!");
    ((args += ""), ...);
};
Run Code Online (Sandbox Code Playgroud)

并且如果您按如下方式更改函数对象:

struct Foo
{
    template <typename ...Ts>
    auto operator ()(Ts... args) const // <---- placeholder as return type
    {
        static_assert(sizeof...(args) == 42, "!");
        ((args += ""), ...);
    }
} foo;
Run Code Online (Sandbox Code Playgroud)

它也可以实例化Foo::operator()以推断返回类型。