考虑下面的代码错误模板实例超载
#include <type_traits>
#include <utility>
template <typename T>
class Something {
public:
template <typename F>
auto foo(F&&)
-> decltype(std::declval<F>()(std::declval<T&>())) {}
template <typename F>
auto foo(F&&) const
-> decltype(std::declval<F>()(std::declval<const T&>())) {}
};
int main() {
auto something = Something<int>{};
something.foo([](auto& val) {
++val;
});
}
https://wandbox.org/permlink/j24Pe9qOXV0oHcA8
当我尝试编译此我得到的错误,说不准我在修改的拉姆达一个const值之前主要。这意味着模板在某种程度上都是在类中实例化的,并且由于错误出现在lambda体中,所以导致了一个硬性错误。
这是什么规则?为什么重载决议尝试实例化一个永远不会被调用的模板? const函数不应该在这里被调用,为什么它会试图完全实例化它?
然而,奇怪的是,当我通过decltype(auto)
更改定义并返回并添加代码以执行与尾随返回类型相同的操作时,我看不到错误。表明模板没有完全实例化?
template <typename F>
decltype(auto) foo(F&& f) {
auto t = T{};
f(t);
}
template <typename F>
decltype(auto) foo(F&& f) const {
const auto t = T{};
f(t);
}
我猜编译器不知道在使用传递函数实例化至少签名之前要调用哪个函数。但是,这并不能解释为什么decltype(自动)版本的作品...
“*实例化过程中会出现错误*”而不是何时?替代是自己的一步? –
@RyanHaining:在替换步骤中,'decltype(...)'尾随返回类型实例化lambda的body ...导致错误。 –
这里有什么建议避免这个问题的方法?只需切换到'decltype(auto)'?我希望'foo'函数对于返回类型是SFINAE友好的,并且还有用户代码工作 – Curious