在未评估的上下文中实例化 template/lambda 是否未指定?
Is it unspecified to instantiate template/lambda in unevaluated context?
我尝试使用以下代码来检查模板是否在未评估的上下文中实例化:
#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
作为模板函数:(无错误)
template <typename ...Ts>
void foo(Ts... args)
{
static_assert(sizeof...(Ts) == 42, "!");
((args += ""), ...);
}
将 foo
作为常规函子:(无错误)
struct Foo
{
template <typename ...Ts>
void operator ()(Ts... args) const
{
static_assert(sizeof...(args) == 42, "!");
((args += ""), ...);
}
} foo;
但是 foo
作为 lambda:(错误)
auto foo = [](auto... args)
{
static_assert(sizeof...(args) == 42, "!"); // Triggers
((args += ""), ...); // spotted as invalid: int += const char*
};
lamdba的operator()
实例化正常吗?
gcc/clang 具有相同的行为。
lambda 案例实际上与其他案例不同!您没有为 lambda 指定 return 类型,因此可以推断出它。要进行推导,必须实例化 lambda。
函数对象不是这种情况,因为您在那里将 return 类型指定为 void
。将 lambda 更改为 return 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()
以能够推断出 return 类型。
我尝试使用以下代码来检查模板是否在未评估的上下文中实例化:
#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
作为模板函数:(无错误)
template <typename ...Ts>
void foo(Ts... args)
{
static_assert(sizeof...(Ts) == 42, "!");
((args += ""), ...);
}
将 foo
作为常规函子:(无错误)
struct Foo
{
template <typename ...Ts>
void operator ()(Ts... args) const
{
static_assert(sizeof...(args) == 42, "!");
((args += ""), ...);
}
} foo;
但是 foo
作为 lambda:(错误)
auto foo = [](auto... args)
{
static_assert(sizeof...(args) == 42, "!"); // Triggers
((args += ""), ...); // spotted as invalid: int += const char*
};
lamdba的operator()
实例化正常吗?
gcc/clang 具有相同的行为。
lambda 案例实际上与其他案例不同!您没有为 lambda 指定 return 类型,因此可以推断出它。要进行推导,必须实例化 lambda。
函数对象不是这种情况,因为您在那里将 return 类型指定为 void
。将 lambda 更改为 return 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()
以能够推断出 return 类型。