If you want to be able to call a function f
for all types that have function member getInt
, not just X
, you can declare 2 overloads for function f
:
for types that have getInt
member function, including class X
for all the other types, including class Y
.
C++11 / C++17 solution
Having that in mind, you could do something like this:
#include <iostream>
#include <type_traits>
template <typename, typename = void>
struct has_getInt : std::false_type {};
template <typename T>
struct has_getInt<T, std::void_t<decltype(((T*)nullptr)->getInt())>> : std::is_convertible<decltype(((T*)nullptr)->getInt()), int>
{};
class X {
public:
int getInt(){
return 9;
}
};
class Y {};
template <typename T,
typename std::enable_if<!has_getInt<T>::value, T>::type* = nullptr>
void f(T& v) {
// only for Y
std::cout << "Y" << std::endl;
}
template <typename T,
typename std::enable_if<has_getInt<T>::value, T>::type* = nullptr>
void f(T& v){
// only for X
int i = v.getInt();
std::cout << "X" << std::endl;
}
int main() {
X x;
f(x);
Y y;
f(y);
}
Check it out live.
Please note that std::void_t
is introduced in C++17, but if you are limited to C++11, then it is really easy to implement void_t
on your own:
template <typename...>
using void_t = void;
And here is C++11 version live.
What do we have in C++20?
C++20 brings lots of good things and one of them is concepts. Above thing that's valid for C++11/C++14/C++17 can be significantly reduced in C++20:
#include <iostream>
#include <concepts>
template<typename T>
concept HasGetInt = requires (T& v) { { v.getInt() } -> std::convertible_to<int>; };
class X {
public:
int getInt(){
return 9;
}
};
class Y {};
template <typename T>
void f(T& v) {
// only for Y
std::cout << "Y" << std::endl;
}
template <HasGetInt T>
void f(T& v){
// only for X
int i = v.getInt();
std::cout << "X" << std::endl;
}
int main() {
X x;
f(x);
Y y;
f(y);
}
Check it out live.
type_info
structure have a equality comparison operator, sotypeid(T) == typeid(X)
should work as well. – Navalif constexpr
with conditionis_same_v<T,X>
. – ReprovegetInt
member. There must be quite a few questions here on stackoverflow.com alone about how to see if a structure or class have a specific member function, if you just search a little. – Navalconstexpr if
is different from a regular if and was introduced in c++17. See en.cppreference.com/w/cpp/language/if . – Remsenv.getInt()
if the condition is true. If you don't have a constexpr if then the compiler will try to build thev.getInt()
call even ifv
doesn't have anygetInt
member function, which will lead to a build error. – Naval