【发布时间】:2018-04-10 14:04:29
【问题描述】:
我对模板化 lambda 中的“if constexpr”有疑问。为了争论,让我们忽略我是如何到达那里的,但我有一个以某种方式定义的 struct foo 导致如下所示:
template<bool condition>
struct foo {
int a;
// Only contains b if condition is true
int b;
}
现在我可以定义一个模板函数 thtemplate
template<bool condition>
void print_fun(foo & obj) {
/* Do something with obj.a */
if constexpr(condition)
/* Do something with obj.b */
};
如果 foo 的 constexpr 参数与 print_fun 的参数相同,则实例化此函数并使用它将编译,即
constexpr bool no = false;
foo<no> obj = {};
print_fun<no>(obj);
这确实可以编译,因为错误分支在模板化实体中被丢弃,因此在 print_fun 中使用 obj.b 没有问题。
但是,如果我定义一个类似的 lambda 表达式如下:
template<bool condition>
auto print_lambda = [](foo & obj) {
/* Do something with obj.a */
if constexpr(condition)
/* Do something with obj.b */
};
并实例化它:
constexpr bool no = false;
foo<no> obj = {};
print_lambda<no>(obj);
那么错误的分支不会被丢弃,编译器给我
'b': 不是'foo'的成员
这是预期的行为,是否发生在其他编译器上? 难道我做错了什么? 或者它是编译器中的错误? (Microsoft Visual Studio 版本 15.4.1,gcc 7.2)
查看我使用 gcc 的测试 here,它也不会针对仿函数或函数进行编译。
编辑:
这是我的最小示例的代码,我不知道外部链接是不够的。这可在 Visual Studio 15.4.1 上编译,但注明的行除外。
foo_bar 在我的描述中取代了foo。
#include <iostream>
constexpr bool no = false;
struct foo {
int x;
};
struct bar {
int y;
};
template <bool, typename AlwaysTy, typename ConditionalTy>
struct Combined : AlwaysTy {};
template <typename AlwaysTy, typename ConditionalTy>
struct Combined<true, AlwaysTy, ConditionalTy> : AlwaysTy, ConditionalTy {};
using foo_bar = Combined<no, foo, bar>;
template<bool condition>
void print_fun(foo_bar & obj) {
std::cout << obj.x << std::endl;
if constexpr(condition)
std::cout << obj.y << std::endl;
};
template<bool condition>
auto print_lambda = [](foo_bar & obj) {
std::cout << obj.x << std::endl;
if constexpr(condition)
std::cout << obj.y << std::endl;
};
int main(int argc, char ** argv) {
foo_bar obj = {};
print_lambda<no>(obj); // Does not compile
print_fun<no>(obj);
}
【问题讨论】:
-
"constexpr 用于创建 foo"。 constexprs 不会创建任何东西。您问题的多个部分令人困惑,无法解析。您需要包含一个特定的minimal reproducible example 来演示您所询问的编译错误,以便每个人都可以自己看到它,而不必猜测它是什么。而且您必须将其包含在问题本身中,而不是指向可能随时停止工作的某个外部网站的链接,从而使问题变得毫无意义。由于这个原因,stackoverflow.com 上的大多数人都会忽略问题中的外部链接。
-
我已经编辑了我的问题以包含该示例。很抱歉造成混淆,我只是不想详细说明 foo 基于 constexpr 是如何变得不同的,但我希望现在已经清楚了。
标签: c++ templates lambda c++17 if-constexpr