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

时间:2019-07-05 10:22:05

标签: c++ templates lambda language-lawyer instantiation

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

  mail.smtp.ssl.trust=*
  mail.smtp.starttls.required=true
  mail.smtp.starttls.enable=true
  mail.smtp.starttls.checkserveridentity=false

#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); 作为模板功能:(无错误)

foo

Demo

template <typename ...Ts> void foo(Ts... args) { static_assert(sizeof...(Ts) == 42, "!"); ((args += ""), ...); } 作为常规函子:(无错误)

foo

Demo

但是struct Foo { template <typename ...Ts> void operator ()(Ts... args) const { static_assert(sizeof...(args) == 42, "!"); ((args += ""), ...); } } foo; 为lambda :(错误)

foo

Demo

实例化lamdba的auto foo = [](auto... args) { static_assert(sizeof...(args) == 42, "!"); // Triggers ((args += ""), ...); // spotted as invalid: int += const char* }; 是否正常?

gcc / clang具有相同的行为。

1 个答案:

答案 0 :(得分:15)

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

函数对象不是这种情况,因为您在此处将返回类型指定为void。更改lambda以返回void来避免扣除,这会使gcc / clang感到高兴。 :)

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

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

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

它也实例化Foo::operator()以便能够推断出返回类型。