2014-05-15 154 views
0

我一直在寻找如何调用一个函数的答案,只有当它存在并发现此问题的一些代码Is it possible to write a template to check for a function's existence?。我试图使用std :: is_member_function_pointer作为鉴别器来调用专门的模板代码。但是我在输出中看到了两次,当我期望看到错误而且是真实的时候。有关这可能是为什么的任何建议?该代码还可以在https://ideone.com/HZ17Wf看出std :: is_member_function_pointer始终返回true

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

namespace Ckb 
{ 

struct Version 
{ 
    enum { Major = 1, Minor = 0, Release = 0 }; 
    void CheckDependencies() 
    { 
     std::cout << "Ckb Check" << std::endl; 
    } 
}; 

} // namespace Ckb 

namespace Cg 
{ 

struct Version { enum { Major = 1, Minor = 8, Release = 1 }; }; 

} // namespace Cg 

template <typename T, bool> struct RunCheck 
{ void operator()() {std::cout << "false" << std::endl;} }; 

template <typename T> struct RunCheck<T, true> 
{ void operator()() { std::cout << "true" << std::endl; } }; 

template <typename T> void Do() 
{ 
    RunCheck<T, std::is_member_function_pointer<void(T::*)()>::value>()(); 
} 

int main() 
{ 
    Do<Cg::Version>(); 
    Do<Ckb::Version>(); 
    return 0; 
} 
+0

你想检查是否'CheckDependencies()'存在(用正确的签名)? – Jarod42

回答

4

void(T::*)()member_function_pointer(即使T没有任何匹配方法)。

我想你想使用类似:

#include <cstdint> 

#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)    \ 
    template <typename U>             \ 
    class traitsName              \ 
    {                  \ 
    private:                \ 
     template<typename T, T> struct helper;        \ 
     template<typename T>            \ 
     static std::uint8_t check(helper<signature, &funcName>*);   \ 
     template<typename T> static std::uint16_t check(...);    \ 
    public:                 \ 
     static                \ 
     constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \ 
    } 

DEFINE_HAS_SIGNATURE(has_CheckDependencies, T::CheckDependencies, void (T::*)()); 

,然后使用它:

template <typename T> void Do() 
{ 
    RunCheck<T, has_CheckDependencies<T>::value>()(); 
} 
+0

非常感谢您的帮助,@ Jarod42。这适用于C++ 11编译器。我已经尝试过其他类型,并简单地改变类型,并且int也可以工作。可悲的是,我使用的目标编译器来自旧的Borland家族(现在是Embarcadero),而版本4不能编译。我认为DEFINE_HAS_SIGNATURE(has_CheckDependencies,T :: CheckDependencies,void(T :: *)())行有问题,因为有些奇怪的原因需要知道T是什么。心理......无论如何,再次感谢您的帮助。 – DSV