C++ 函数重载,enable_if 的替代方案?

C++ function overloading, alternatives to enable_if?

如果我在模板化 class 中有一个函数 insert,我会重载它以采用填充模式:

void insert(const size_type N, const value_type &element);

或范围模式:

template <class iterator_type>
void insert(const iterator_type begin, const iterator_type end)

当我将 class 的 value_type 指定为 int 时,会导致以下调用:

insert(500, 50);

不明确,因为它假设 500 是一个 int,因此不匹配 size_type N,而不是调用填充模式函数,而是调用模板化范围函数失败了。

这是一个C++03兼容的库,它不能使用像boost这样的外部库,只能使用内置的C++代码。我发现唯一不需要 C++11 的 enable_if 的解决方法是创建额外的重载,将 size_type 替换为 intlong intchar 等,并从中调用填充函数。显然这是有问题的,因为你可以有这么多不同的类型匹配 500。有什么建议吗?

充分利用 SFINAE:

void insert(const size_type N, const value_type &element);

template <class iterator_type>
void insert(iterator_type begin, iterator_type end, char (*)[sizeof(*begin)] = NULL);

范围版本insert中的额外伪参数将被编译器优化掉。它的唯一作用是消除模板函数对不能与取消引用运算符一起使用的类型的重载解析。

技巧说明:

char (*)[sizeof(*begin)]代表一个指向大小等于sizeof(*begin)的字符数组的指针。如果变量 begin 不可取消引用,那么这将是一个错误。但是,在函数重载解析期间考虑函数模板的上下文中,这样的错误不会停止编译,而只是丢弃模板(替换失败不是错误 - SFINAE)。

根据您支持的确切编译器,您可能会发现 enable_if 无论如何都是内置的 - 它存在于 TR1 中。

但是,enable_if 的实现很简单。您也可以简单地从 Boost 复制它。事实上,它太短了,我将在这个答案中 post 它。

namespace boost
{

  template <bool B, class T = void>
  struct enable_if_c {
    typedef T type;
  };

  template <class T>
  struct enable_if_c<false, T> {};

  template <class Cond, class T = void> 
  struct enable_if : public enable_if_c<Cond::value, T> {};

  template <bool B, class T>
  struct lazy_enable_if_c {
    typedef typename T::type type;
  };

  template <class T>
  struct lazy_enable_if_c<false, T> {};

  template <class Cond, class T> 
  struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};


  template <bool B, class T = void>
  struct disable_if_c {
    typedef T type;
  };

  template <class T>
  struct disable_if_c<true, T> {};

  template <class Cond, class T = void> 
  struct disable_if : public disable_if_c<Cond::value, T> {};

  template <bool B, class T>
  struct lazy_disable_if_c {
    typedef typename T::type type;
  };

  template <class T>
  struct lazy_disable_if_c<true, T> {};

  template <class Cond, class T> 
  struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};

} // namespace boost

在 Puppy 的回答的帮助下弄明白了:

// Fill insert
void insert(const size_type N, const value_type &element);


// Enable_if template
template <bool condition, class T = void> 
struct enable_if_c
{
    typedef T type;
};

template <class T>
struct enable_if_c<false, T>
{};


// Range insert:
template <class iterator_type>
iterator insert (const typename enable_if_c<!std::numeric_limits<iterator_type>::is_integer, iterator_type>::type &first, const iterator_type &last);

numeric_limits 是 C++03 安全的,适用于所有(经过测试的)编译器,包括 MSVC 2010。这将检查以确保提供给范围插入的类型不是整数。