仅对定义了功能的类型在功能模板内执行功能 [英] Execute function inside function template only for those types that have the function defined

查看:68
本文介绍了仅对定义了功能的类型在功能模板内执行功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数模板,它接受许多不同类型的输入.在这些类型中,只有一种具有getInt()函数.因此,我希望代码仅针对该类型运行该函数.请提出解决方案.谢谢

I have a function template which takes many different types as it's input. Out of those types only one of them has a getInt() function. Hence I want the code to run the function only for that type. Please suggest a solution. Thanks

#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);
}

推荐答案

如果您希望能够为具有函数成员getInt的所有类型(而不仅仅是X)调用函数f,则可以声明函数f的2个重载:

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:

  1. 用于具有getInt成员函数的类型,包括类X

  1. for types that have getInt member function, including class X

用于所有其他类型,包括类Y.

for all the other types, including class Y.

C ++ 11/C ++ 17解决方案

请记住,您可以执行以下操作:

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);
}

检查出来活.

请注意,C ++ 17中引入了 std::void_t ,但是如果您仅限于C ++ 11,那么单独实现void_t真的很容易:

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;

和这里是C ++ 11版本.

And here is C++11 version live.

我们在C ++ 20中拥有什么?

C ++ 20带来了很多好处,其中之一就是概念.在C ++ 20中可以大大降低上述对C ++ 11/C ++ 14/C ++ 17有效的东西:

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);
}

检查 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆