给定以下代码
#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
当我尝试编译它时,我收到错误消息,说我不允许在 main 中修改 lambda 中的 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(auto) 版本有效......