Motivation: one has a function that accepts either a lambda or a value (for simplicity it can be either const char *
or std::string
) like following
template <typename LambdaOrValue>
void Function(LambdaOrValue &&lambda_or_value) {
// The idea here is to have sort of a magic that
// evaluates a lambda if an argument is actually
// a lambda or do nothing otherwise
if (Evaluate(std::forward<LabmdaOrValue>(lambda_or_value)) ==
std::string("pattern"))
// Do something
}
I'm struggling to properly implement a function Evaluate()
i.e. to make the code below compile. In particular, which return value to use in the "value"-based implementation to
preserve the type (e.g. const char *
or std::string
)
#include <type_traits>
#include <iostream>
template <typename T>
decltype(std::declval<T>()()) Evaluate(T &&t) {
return t();
}
template <typename T>
T Evaluate(T &&t) { // <<--- What return type use here to preserve the type
return std::forward<T>(t);
}
int main() {
std::cout << Evaluate("test") << std::endl;
std::cout << Evaluate([]() { return "lambda"; }) << std::endl;
}
CodePudding user response:
Since you have access to C 17, why not use std::is_invocable
, if constexpr
and decltype(auto)
combo?
template <typename T>
auto Evaluate(T &&t) -> decltype(auto){
if constexpr (std::is_invocable_v<T>)
return t();
else
return std::forward<T>(t);
}