c ++ 03:感谢enable_if的互斥方法

时间:2017-06-19 07:21:48

标签: c++ boost sfinae 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()
    { }
}

这不会编译。

  

错误:模板参数列表中参数1的类型/值不匹配'template struct boost :: enable_if'    错误:期待一种类型,得到'!升压:: is_same ::值'

4 个答案:

答案 0 :(得分: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();
};

答案 1 :(得分: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_с,因为!运算符不适用于某种类型。

答案 2 :(得分: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"
 }

答案 3 :(得分:-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