2014-09-29 140 views
5

我试图确定各种C++成员函数的返回类型。我明白,decltype和std :: declval可以用来做到这一点,但我遇到了语法问题并找到了有用的例子。下面的TestCBClass显示了一个包含混合静态和常规成员函数的哑类的示例 - 带有无参数和返回类型的&。根据所讨论的方法,我希望能够从各种方法中声明一个返回类型的向量。如何确定C++ 11成员函数的返回类型

在我的应用程序中,这些方法是std::async的回调,我需要一个向量std::future<return types>。我已经尝试过各种声明,如decltype(std::declval(TestCBClass::testStaticMethod))(我不确定在方法名称前是否需要&)。这种语法是不正确的 - 当然它不能编译,但我认为它应该使用的方法。

class TestCBClass { 
public: 
    TestCBClass(const int& rValue = 1) 
     : mValue(rValue) { 
     std::cout << "~TestCBClass()" << std::endl; 
    } 
    virtual ~TestCBClass() { 
     std::cout << "~TestCBClass()" << std::endl; 
    } 
    void testCBEmpty(void) { 
     std::cout << "testCBEmpty()" << std::endl; 
    } 
    int testCBArgRet(const int& rArg) { 
     std::cout << "testCBArgRet(" << rArg << ")" << std::endl; 
     mValue = rArg; 
    } 
    static void testCBEmptyStatic(void) { 
     std::cout << "testCBEmptyStatic()" << std::endl; 
    } 
    static void cbArgRetStatic(const SLDBConfigParams& rParams) { 
     std::lock_guard<std::mutex> lock(gMutexGuard); 
     std::cout << rParams.mPriority << std::endl; 
    } 
    static std::string testStaticMethod(const PriorityLevel& rPrty) { 
     return "this is a silly return string"; 
    } 
private: 
    int mValue; 
}; 

回答

5

你也可以使用std::result_ofdecltype,如果你喜欢列出的参数类型,而不是相应的虚值,就像这样:

#include <iostream> 
#include <utility> 
#include <type_traits> 

struct foo { 
    int memfun1(int a) const { return a; } 
    double memfun2(double b) const { return b; } 
}; 

int main() { 
    std::result_of<decltype(&foo::memfun1)(foo, int)>::type i = 10; 
    std::cout << i << std::endl; 
    std::result_of<decltype(&foo::memfun2)(foo, double)>::type d = 12.9; 
    std::cout << d << std::endl; 
} 

DEMO here.

+0

非常好,简单!谢谢 – johnco3 2014-09-29 20:31:18

3

如何确定一个C++ 11的成员函数的返回类型?

答:

你可以使用decltypestd::declval像下面的玩具例子:

#include <iostream> 
#include <utility> 

struct foo { 
    int memfun1(int a) const { return a; } 
    double memfun2(double b) const { return b; } 
}; 

int main() { 
    decltype(std::declval<foo>().memfun1(1)) i = 10; 
    std::cout << i << std::endl; 
    decltype(std::declval<foo>().memfun2(10.0)) d = 12.9; 
    std::cout << d << std::endl; 
} 

LIVE DEMO

+0

谢谢,会发生什么,如果memfun1()或memfun2 T() ake参数 - 在我的情况下,我的testStaticMethod需要一个PriorityLevel对象 - 这不是默认的可构造的 - 我认为这是什么declval是正确的?还有一件事,我忘了问我的问题 - 是否可以打印出类型为字符串? – johnco3 2014-09-29 19:18:54

+0

@ johnco3你只需要输入一些虚拟输入参数。我编辑了答案。 – 101010 2014-09-29 19:22:41

+0

@ johnco3 Yeap'declval'确保对象的构造函数不会被引发。你可以使用['typeid'](http://en.cppreference.com/w/cpp/language/typeid)来获得一个类型的字符串。更好的方法是使用'type_traits',特别是['std :: is_same'](http://en.cppreference.com/w/cpp/types/is_same)来检查一个类型是否与另一个类型相同。 – 101010 2014-09-29 19:26:18

4

我已经尝试了各种宣言,如decltype (性病:: declval(TestCBClass :: testStaticMethod))

不必使用std::declval并传递实际参数,甚至没有它们的类型,只知道什么是回报静态/非静态成员函数的类型。相反,你可以写自己的特质才知道什么是给定函数的返回类型:

template <typename T> 
struct return_type; 
template <typename R, typename... Args> 
struct return_type<R(*)(Args...)> { using type = R; }; 
template <typename R, typename C, typename... Args> 
struct return_type<R(C::*)(Args...)> { using type = R; }; 
template <typename R, typename C, typename... Args> 
struct return_type<R(C::*)(Args...) const> { using type = R; }; 
template <typename R, typename C, typename... Args> 
struct return_type<R(C::*)(Args...) volatile> { using type = R; }; 
template <typename R, typename C, typename... Args> 
struct return_type<R(C::*)(Args...) const volatile> { using type = R; }; 
template <typename T> 
using return_type_t = typename return_type<T>::type; 

... 

TestCBClass t; 

std::future<return_type_t<decltype(&TestCBClass::testCBArgRet)>> a = 
     std::async(&TestCBClass::testCBArgRet, t, 1); 

std::future<return_type_t<decltype(&TestCBClass::testCBEmpty)>> b = 
     std::async(&TestCBClass::testCBEmpty, t); 

std::future<return_type_t<decltype(&TestCBClass::testCBEmptyStatic)>> c = 
     std::async(&TestCBClass::testCBEmptyStatic); 

DEMO

+0

非常好 - 它工作(天知道为什么;))类型特征不是我的东西 - 虽然std :: result_of似乎更简单和更容易使用模板机器全部隐藏在封面下。检查答案是有用的 – johnco3 2014-09-29 20:30:27

+0

@ johnco3:如果你喜欢重复函数参数的类型,每次你声明'std :: future',那么是的,你可以使用'std :: result_of' – 2014-09-29 20:34:52

相关问题