【发布时间】:2017-10-11 14:05:48
【问题描述】:
给定以下代码
#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) 版本有效...
【问题讨论】:
标签: c++ c++11 templates overloading template-instantiation