Checking member function overload existence from a template
是否可以从模板成员函数中检查类是否具有某个成员函数重载?
我能找到的最好的类似问题是:是否可以编写一个模板来检查函数的存在?据我所知,这不适用于检查函数过载的情况。
下面是一个简单的例子,说明如何应用这一点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | struct A; struct B; class C { public: template<typename T> void doSomething(std::string asdf) { T data_structure; /** some code */ if(OVERLOAD_EXISTS(manipulateStruct, T)) { manipulateStruct(data_structure); } /** some more code */ } private: void manipulateStruct(B& b) {/** some different code */}; } |
我的问题是,是否存在某种标准方法来使代码的以下用法起作用:
1 2 3 4 5 6 7 | int main(int argc, const char** argv) { C object; object.doSomething<A>("hello"); object.doSomething("world"); exit(0); } |
我能想到的唯一方法是简单地为结构
有没有办法让类似上面的代码工作?是否存在类似于
测试过载的存在(C++ 11)
由于C++ 11,您可以使用STD::DECVALL和DeCyType的混合来测试特定过载的存在:
1 2 3 | // If overload exists, gets its return type. // Else compiler error decltype(std::declval<C&>().manipulateStruct(std::declval<T&>())) |
这可以在sfinae结构中使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class C { public: // implementation skipped private: // Declared inside class C to access its private member. // Enable is just a fake argument to do SFINAE in specializations. template<typename T, typename Enable=void> struct can_manipulate; } template<typename T, typename Enable> struct C::can_manipulate : std::false_type {}; // Implemented outside class C, because a complete definition of C is needed for the declval. template<typename T> struct C::can_manipulate<T,std::void_t<decltype(std::declval<C&>().manipulateStruct(std::declval<T&>()))>> : std::true_type {}; |
在这里,我忽略了使用STD::VoIDyt(C++ 17,但C++ 11个替代品应该是可能的)超载的返回类型。如果要检查返回类型,可以将其传递给std::is_same或std::is_assignable。
剂量测定实施C++ 17这可以通过constexpr完成,如果:
1 2 3 4 5 6 7 | template<typename T> void doSomething(std::string asdf) { T data_structure; if constexpr (can_manipulate<T>::value) { manipulateStruct(data_structure); } } |
如果条件的计算结果为false,则
实况演示(C++ 17完整代码)
C++ 11您可以使用sfinae模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class C { // previous implementation private: template<typename T, typename Enable=void> struct manipulator; } template<typename T, typename Enable> struct C::manipulator { static void call(C&, T&) { //no-op } }; // can_manipulate can be inlined and removed from the code template<typename T> struct C::manipulator<T, typename std::enable_if<C::can_manipulate<T>::value>::type> { static void call(C& object, T& local) { object.manipulateStruct(local); } }; |
功能体:
1 2 3 4 5 6 7 | template<typename T> T doSomething() { T data_structure; // replace if-constexpr: manipulator<T>::call(*this, data_structure); } |
实况演示(C++ 11完整代码)