mercredi 11 octobre 2017

Error in template instantiation before overloading

Given the following code

#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;
    });
}

http://ift.tt/2yZL2jF

When I try to compile this I get the error saying that I am not allowed to modify a const value in the lamdba in main. This means that somehow the templates are both being instantiated in the class and this is causing a hard error since the error is in the body of the lambda.

What are the rules regarding this? Why does overload resolution try to instantiate a template that will never be called? The const one should never be called here so why does it try to fully instantiate it?


However strange thing here is that when I change the definitions to return by decltype(auto) and add the code to do the same thing as the trailing return types suggest, I don't see an error. Indicating that the templates are not fully being instantiated?

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);
}

Aucun commentaire:

Enregistrer un commentaire