以下不编译:
#include <iostream>
#include <type_traits>
template <class F, class G>
auto static_if (std::true_type, F && f, G && g) {
return std::forward<F> (f) (0);
}
template <class F, class G>
auto static_if (std::false_type, F && f, G && g) {
return std::forward<G> (g) (0);
}
template <class T> std::true_type constexpr is_pointer (T *) { return {}; }
template <class T> std::false_type constexpr is_pointer (T) { return {}; }
int main() {
int x = 5;
static_if (
is_pointer (x),
[&] (auto) { std::cout << *x << std::endl; },
[&] (auto) { std::cout << "no pointer" << std::endl; }
);
return 0;
}
编译失败并显示错误信息:
prog.cpp: In lambda function:
prog.cpp:23:33: error: invalid type argument of unary '*' (have 'int')
[&] (auto) { std::cout << *x << std::endl; },
现在的问题是:为什么?
很明显,如果 lambda 不是通用的(没有 auto
参数),编译应该会失败。
然而,我们这里有两个通用 lambda。它们中的每一个都应该只在使用时实例化(这意味着:被调用,或者至少,当它的 operator ()
以某种方式被引用时)。
因此,生成错误消息的通用 lambda 应该不被实例化,因为使用了 static_if
的第二个重载,在其定义中参数 f
未被调用。由于未使用通用 lambda 的 operator ()
,因此编译器应该简单地忽略它。
我的推理哪里错了?
最佳答案
在对已接受答案的评论中,您询问是否有更好的解决方案。可以说下面是一个(实时代码 here )。您不是在本地捕获 x,而是将您的 static_if
泛化为将任何参数一般地转发给两个 lambda 之一,并使您的 x
成为这样的参数。那么你就不需要在评论中使用虚拟变量了。
template <class F, class G, class ... Args>
auto static_if (std::true_type, F && f, G && g, Args && ... args) {
return std::forward<F> (f) (std::forward<Args>(args)...);
}
template <class F, class G, class ... Args>
auto static_if (std::false_type, F && f, G && g, Args && ... args) {
return std::forward<G> (g) (std::forward<Args>(args)...);
}
template <class T> std::true_type constexpr is_pointer (T *) { return {}; }
template <class T> std::false_type constexpr is_pointer (T) { return {}; }
int main() {
int x = 5;
static_if (
is_pointer (x),
[] (auto x) { std::cout << *x << std::endl; },
[] (auto x) { std::cout << "no pointer" << std::endl; },
x
);
return 0;
}
关于c++ - 泛型 lambda 的实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38455947/