2017-06-19 42 views
2

在一个类中,我有两种不同的方法,根据调用者模板参数应该是相互排斥的。C++ 03:相互排斥的方法,由于enable_if

class Foo 
{ 
    // For collections 
    template<class T> 
    typename boost::enable_if<boost::is_same<typename std::vector<typename T::value_type>, T>::value, const T&>::type 
    doSomething() 
    { } 


    // For single types 
    template<class T> 
    typename boost::enable_if<!boost::is_same<typename std::vector<typename T::value_type>, T>::value, const T&>::type 
    doSomething() 
    { } 
} 

这不会编译。

error: type/value mismatch at argument 1 in template parameter list for 'template struct boost::enable_if' error: expected a type, got '! boost::is_same::value'

+2

也许你想'boost :: enable_if_c'?见例如[Boost enable_if参考](http://www.boost.org/doc/libs/1_64_0/libs/core/doc/html/core/enable_if.html)。 –

+0

为什么不能使用'disable_if' – danielspaniol

+2

奇怪,为什么在'doSomething()'之前指定'const T&',因为返回类型应该已经由'typename boost :: enable_if ...'指定了? – Alexey

回答

-1

如果你想要的是超载基础上的功能是否给你一个载体或不

#include <type_traits> 
#include <iostream> 
#include <vector> 

using std::cout; 
using std::endl; 

class Foo { 
public: 
    // For collections 
    template <class T> 
    const vector<T>& do_something(const std::vector<T>& input) { 
     cout << __PRETTY_FUNCTION__ << endl; 
     return input; 
    } 


    // For single types 
    template <class T> 
    const T& do_something(const T& input) { 
     cout << __PRETTY_FUNCTION__ << endl; 
     return input; 
    } 
}; 

int main() { 
    auto foo = Foo{}; 
    auto v = std::vector<int>{}; 
    auto i = int{}; 
    foo.do_something(v); 
    foo.do_something(i); 
} 

如果你想更加普遍和检查任何实例化的类型

#include <type_traits> 
#include <iostream> 
#include <vector> 

using std::cout; 
using std::endl; 

namespace { 

    template <typename T, template <typename...> class TT> 
    struct IsInstantiationOf 
      : public std::integral_constant<bool, false> {}; 
    template <template <typename...> class TT, typename... Args> 
    struct IsInstantiationOf<TT<Args...>, TT> 
      : public std::integral_constant<bool, true> {}; 
} // namespace anonymous 

class Foo { 
public: 
    // For collections 
    template <typename VectorType, typename std::enable_if_t<IsInstantiationOf< 
      std::decay_t<VectorType>, std::vector>::value>* = nullptr> 
    void do_something(VectorType&&) { 
     cout << "Vector overload" << endl; 
    } 

    // For single types 
    template <class T, typename std::enable_if_t<!IsInstantiationOf< 
      std::decay_t<T>, std::vector>::value>* = nullptr> 
    void do_something(T&&) { 
     cout << "Non vector overload" << endl; 
    } 
}; 

int main() { 
    auto foo = Foo{}; 
    auto v = std::vector<int>{}; 
    auto i = int{}; 
    foo.do_something(v); 
    foo.do_something(i); 
} 

另请注意,您应该避免将std::enable_if放在函数签名中,可能由于这些原因https://stackoverflow.com/a/14623831/5501675

+0

函数的返回类型是模板类型T,我无法用简单的函数重载进行排序,我需要SFINAE – codeJack

+0

@codeJack再次编辑使用SFINAE,如果这是你想要的 – Curious

+0

@downvoter为什么downvote? – Curious

1

如何:

template <typename T> struct is_std_vector : std::false_type {}; 
template <typename T, typename A> 
struct is_std_vector<std::vector<T, A>> : std::true_type {}; 

然后

class Foo 
{ 
    // For collections 
    template<class T> 
    typename std::enable_if<is_std_vector<T>::value, const T&>::type 
    doSomething(); 

    // For single types 
    template<class T> 
    typename std::enable_if<!is_std_vector<T>::value, const T&>::type 
    doSomething(); 
}; 
+0

这种有效。但为什么我不能使用自己的语法而不需要定义is_std_vector结构? – codeJack

+1

'T :: value_type'没有为所有类型定义,所以你SFINAE也是这样,它对于大多数非容器类型都是不正确的。 – Jarod42

0

不像std的版本,boost::enable_if接受型(下布尔值还挺包装器),所以你应该喜欢写东西

class Foo 
{ 
    // For collections 
    template<class T> 
    typename boost::enable_if< 
     typename boost::is_same<typename std::vector<typename T::value_type>, T>, 
    const T&>::type doSomething() 
    { } 


    // For single types 
    template<class T> 
    typename boost::enable_if_с< 
     !boost::is_same<typename std::vector<typename T::value_type>, T>::value, 
    const T&>::type doSomething() 
    { } 
} 

请注意这里,我已经使用typename之前boost::is_same,并没有在第一个规范中使用::value。相反,我不得不在第二次过载中使用enable_if_с,因为!运算符不适用于某个类型。

0

怎么样的一种标签调度?

#include <vector> 
#include <iostream> 

template <typename, typename> 
struct isSame 
{ typedef int type; }; 

template <typename T> 
struct isSame<T, T> 
{ typedef long type; }; 

struct foo 
{ 
    template <typename T> 
    T const & doSomething (T const & t, int) 
    { std::cout << "int version" << std::endl; return t; } 

    template <typename T> 
    T const & doSomething (T const & t, long) 
    { std::cout << "long version" << std::endl; return t; } 

    template <typename T> 
    T const & doSomething (T const & t) 
    { return doSomething(t, typename isSame< 
     typename std::vector<typename T::value_type>, T>::type()); } 
}; 

int main() 
{ 
    foo f; 
    std::vector<int> v; 
    f.doSomething(v); // print "long version" 
}