我有一个函数模板,它接受许多不同的类型。在这些类型中,只有一种具有getInt()
函数。因此,我希望代码仅针对该类型运行函数。请提出解决方案。谢谢
#include <type_traits>
#include <typeinfo>
class X {
public:
int getInt(){
return 9;
}
};
class Y{
};
template<typename T>
void f(T& v){
// error: 'class Y' has no member named 'getInt'
// also tried std::is_same<T, X>::value
if(typeid(T).name() == typeid(X).name()){
int i = v.getInt();// I want this to be called for X only
}
}
int main(){
Y y;
f(y);
}
最佳答案
如果您希望能够为具有函数成员f
的所有类型调用函数getInt
,而不仅仅是X
,则可以为f
函数声明2个重载:
getInt
成员函数的类型,包括类X
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);
}
checkout live。
请注意
std::void_t
是C++ 17中引入的,但是如果您限于C++ 11,那么自己实现void_t
真的很容易:template <typename...>
using void_t = void;
这是C++ 11版本live。
在C++ 20中我们有什么?
C++ 20带来了很多美好的事物,其中之一就是concepts。以上对于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);
}
checkout live。
关于c++ - 仅对定义了功能的类型在功能模板内执行功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60112341/