简体   繁体   English

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

[英]C++ function overloading, alternatives to enable_if?

If I have a function, insert , within a templated class, and I overload it to take either a fill pattern: 如果有函数,请在模板化类中insert ,然后将其重载以采用填充模式:

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

or a range pattern: 或范围模式:

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

When I specify the value_type of the class to be int, it results in the following call: 当我将类的value_type指定为int时,将导致以下调用:

insert(500, 50);

being ambiguous, as it assumes 500 to be an int and therefore not a match for size_type N , and instead of calling the fill pattern function, calls the templated range function and fails. 是模棱两可的,因为它假定500是一个int ,因此不匹配size_type N ,并且不调用填充模式函数,而是调用模板化范围函数,并且失败。

This is a C++03-compatible library,- it can't use external libraries like boost, only builtin C++ code. 这是C ++ 03兼容的库,不能使用boost等外部库,只能使用内置的C ++代码。 The only workaround I've found that doesn't require C++11's enable_if would be creating additional overloads, replacing size_type with int , long int , char etc, and calling the fill function from them. 我发现不需要C ++ 11的enable_if的唯一解决方法是创建其他重载,用intlong intchar等替换size_type ,并从它们调用fill函数。 Obviously this is problematic because you can have so many different types which match 500 . 显然这是有问题的,因为您可以有许多不同的类型匹配500 Any suggestions? 有什么建议么?

Take advantage of SFINAE: 利用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);

The extra dummy argument in the range version of insert will be optimized out by the compiler. insert范围版本中的额外哑元参数将由编译器优化。 Its only role is to eliminate the template function from overloading resolution for types that cannot be used with a dereference operator. 它唯一的作用是消除模板函数的重载解析,以解决不能与取消引用运算符一起使用的类型。

Clarification of the trick: 技巧说明:

char (*)[sizeof(*begin)] stands for a pointer to an array of chars whose size is equal to sizeof(*begin) . char (*)[sizeof(*begin)]表示一个指向大小等于sizeof(*begin)的char数组的指针。 If the variable begin is not dereferenceable then this would be an error. 如果变量begin无法取消引用,则将是一个错误。 However, in the context of considering a function template during function overload resolution, such an error doesn't stop compilation, but simply discards the template (Substitution Failure Is Not An Error - SFINAE). 但是,在函数重载解析期间考虑函数模板的情况下,此类错误不会停止编译,而只会丢弃模板(“替换失败不是错误-SFINAE”)。

Depending on the exact compilers you support, you may find enable_if as a builtin anyway- it's present in TR1. 根据您支持的确切编译器,无论如何,enable_if都可能是内置的,它存在于TR1中。

However, the implementation of enable_if is trivial. 但是,enable_if的实现很简单。 You could simply copy it from Boost as well. 您也可以直接从Boost复制它。 In fact, it's so short I'm going to post it in this answer. 实际上,它太短了,我将在此答案中发布它。

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

With help from Puppy's answer figured it out: 在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 is C++03-safe and works in all (tested) compilers including MSVC 2010. This checks to make sure the type supplied to range-insert is not an integer. numeric_limits是C ++ 03安全的,并且在包括MSVC 2010在内的所有(经过测试)编译器中均可使用。此检查确保提供给range-insert的类型不是整数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM