だけでなく、f
functionメンバーを持つすべての型の関数を呼び出すことができるようにしたい場合は、function に2つのオーバーロードを宣言できます。getInt
X
f
getInt
クラスを含む、メンバー関数を持つ型の場合X
classを含む他のすべてのタイプの場合Y
。
C ++ 11 / C ++ 17ソリューション
それを念頭に置いて、次のようなことができます。
#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);
}
ライブでご覧ください。
これstd::void_t
はC ++ 17で導入されていますが、C ++ 11に限定されている場合はvoid_t
、自分で実装するのが本当に簡単です。
template <typename...>
using void_t = void;
そしてここにC ++ 11バージョンのライブがあります。
C ++ 20には何がありますか?
C ++ 20には多くの優れた機能があり、そのうちの1つは概念です。上記のC ++ 11 / C ++ 14 / C ++ 17に有効なものは、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);
}
ライブでご覧ください。
type_info
構造には等価比較演算子があるためtypeid(T) == typeid(X)
、同様に機能するはずです。