2014-07-08 150 views
3

说我得到了这样的模板功能

template <typename T> bool func(T a) 
{ 
    if(a.X()) 
    return a.Y(); 
    return false; 
} 

模板函数现在每类我作为参数使用此功能有功能X(), 但不我用作参数的每个类都有函数Y()。 但是,如果函数a.X()返回true,那么我已经保证给定的类具有函数Y()。我可以让这段代码以某种方式编译,因为我知道函数Y()哪个编译器会抱怨某些类型的错误永远不会被调用?这个功能实际上非常大,使用的类型很多,因此使许多专业化是不切实际的。

+0

只有在编译时可以评估'T :: X()',编译时才知道'a',但是涉及到一些模板bla bla,这才会起作用。请澄清是否是这种情况!如果情况并非如此,那么在编译时无法检测到情况,其中'T :: X()'返回true,但是'T :: Y()'不存在。但是,您可以在运行时执行此操作。 –

+1

'if(a)return b;返回false;'是写'return a和b;'的复杂方式。 –

回答

3

SFINAE可能会有帮助,这样的:(https://ideone.com/XmjQY8

#include <type_traits> 
#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_X, T::X, bool (T::*)()); 
DEFINE_HAS_SIGNATURE(has_Y, T::Y, bool (T::*)()); 

template <typename T> 
typename std::enable_if<has_X<T>::value && has_Y<T>::value, bool>::type 
func(T a) 
{ 
    if(a.X()) 
    return a.Y(); 
    return false; 
} 

template <typename T> 
typename std::enable_if<!has_X<T>::value || !has_Y<T>::value, bool>::type 
func(T /*a*/) 
{ 
    return false; 
} 
+0

确定这看起来像答案 - 我不知道type_traits是什么,究竟发生了什么,但我会研究它 – user1316208

2

下面是this answer启发另一个版本,这是一个短一点(和意见:)更好)。

struct Action 
{ 
    template <typename T> 
    static bool func_real(T a){return func(a, special_());} 

private: 

    struct general_ {}; 
    struct special_ : general_ {}; 
    template<typename> struct bool_ { typedef bool type; }; 

    template<typename S, typename bool_<decltype(std::declval<S>().Y())>::type = 0> 
    static bool func(S a, special_) { 
     cout<<"Y() exists"<<endl; 
     if(a.X()){ 
      return a.Y(); 
     } 
     return false; 
    } 

    template<typename S> 
    static bool func(S a, general_) { 
     cout<<"Y() does not exist"<<endl; 
     return false; 
    } 
}; 

Here是一个现场演示。

+0

好的解决方案。试图找出类似的东西,但没有成功。你能向我解释为什么模板参数中的“= 0”有效吗? – JohnB

+0

@JohnB:'0'是'false'。 – Jarod42

+0

@JohnB这是为了给这个参数一个默认值,所以如果有一个正确的'Y'参数将被初始化而不需要明确地指定它(你可以放置'true'或'42' :)) 。 – Scis