/ / Compile-Time-Schalter für mutables / unveränderliches Lambda-c ++, Lambda, c ++

Kompilierzeitschalter für veränderbares / unveränderliches Lambda - C ++, Lambda, C ++ 14

Ich schreibe eine Klassenmitgliederfunktion, die ein Lambda mit einem bestimmten Typ aufnehmen wird T im Funktionsargument. Meine Frage ist: Ist es möglich, die Member-Funktion zur Kompilierzeit aufgrund der Veränderlichkeit des Arguments zu überladen? Unten ist das Beispiel:

// T is a given type for class.
template <typename T>
class Wrapper {

T _t;

// For T&
template <typename F, typename R = std::result_of_t<F(T&)>>
std::enable_if_t<std::is_same<R, void>::value> operator()(F&& f) {
f(_t);
}

// For const T&
template <typename F, typename R = std::result_of_t<F(const T&)>>
std::enable_if_t<std::is_same<R, void>::value> operator()(F&& f) const {
f(_t);
}
};

Also, was ich will ist, wenn das gegebene Lambda die folgende Signatur hat, sollte der erste Operator aufgerufen werden.

[](T&) {
...
};

Für ein konstantes Argument sollte das zweite aufgerufen werden.

[](const T&) {
}

Antworten:

1 für die Antwort № 1

Wenn Sie nur nicht erfassende Lambdas verwenden möchten, können Sie sich darauf verlassen, dass sie auf Zeiger auf Funktionen zerfallen.
Es folgt ein minimales Funktionsbeispiel:

#include<type_traits>
#include<iostream>

template <typename T>
class Wrapper {
T _t;

public:
auto operator()(void(*f)(T &)) {
std::cout << "T &" << std::endl;
return f(_t);
}

auto operator()(void(*f)(const T &)) const {
std::cout << "const T &" << std::endl;
return f(_t);
}
};

int main() {
Wrapper<int> w;
w([](int &){});
w([](const int &){});
}

Ansonsten können Sie zwei überladene Funktionen wie folgt verwenden:

#include<type_traits>
#include<iostream>
#include<utility>

template <typename T>
class Wrapper {
T _t;

template<typename F>
auto operator()(int, F &&f)
-> decltype(std::forward<F>(f)(const_cast<const T &>(_t))) const {
std::cout << "const T &" << std::endl;
return std::forward<F>(f)(_t);
}

template<typename F>
auto operator()(char, F &&f) {
std::cout << "T &" << std::endl;
return std::forward<F>(f)(_t);
}

public:
template<typename F>
auto operator()(F &&f) {
return (*this)(0, std::forward<F>(f));
}
};

int main() {
Wrapper<int> w;
w([](int &){});
w([](const int &){});
}