Consider an overloaded function
void f(int);
void f(long);
void f(double);
void f(MyClass);
And a method in a template class with unknown argument type
template <class T>
struct C {
void method(T arg) { ... }
};
I want to check at compile time if there is a version of f
which can take arg
as an argument.
template <class T>
struct C {
void method(T arg) {
if constexpr (CAN_BE_CALLED(f, arg)) {
f(arg);
} else {
g();
}
}
};
Is it possible to do that? I tried this and this but compiler complained about unresolved overloaded function type.
At compile time, the compiler chooses which overload to use based on the types and number of arguments passed in by the caller. If you call print(42.0) , then the void print(double d) function is invoked. If you call print("hello world") , then the void print(std::string) overload is invoked.
This feature is present in most of the Object Oriented Languages such as C++ and Java. But C doesn't support this feature not because of OOP, but rather because the compiler doesn't support it (except you can use _Generic).
Operator overloading is a compile-time polymorphism.
The call is resolved for an overloaded subroutine by an instance of function through a process called Argument Matching also termed as the process of disambiguation.
You could use the detection idiom to build such a test
template<typename = void, typename... Args>
struct test : std::false_type {};
template<typename... Args>
struct test<std::void_t<decltype(f(std::declval<Args>()...))>, Args...>
: std::true_type {};
template<typename... Args>
inline constexpr bool test_v = test<void, Args...>::value;
And use it as
template <class T>
struct C
{
void method(T arg)
{
if constexpr (test_v<T>)
f(arg);
else
g();
}
};
Live
Or alternatively
template<typename... Args>
using test_t = decltype(f(std::declval<Args>()...));
template<typename... Args>
inline constexpr auto test_v = std::experimental::is_detected_v<test_t, Args...>;
You might do the following with SFINAE:
template <class T, typename Enabler = void>
struct C {
void method(T arg) {
g();
}
};
template <class T>
struct C<T, std::void_t<decltype(f(std::declval<T>()))>> {
void method(T arg) {
f(arg);
}
};
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With