简体   繁体   中英

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:

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:

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.

This is a C++03-compatible library,- it can't use external libraries like boost, only builtin C++ code. 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. Obviously this is problematic because you can have so many different types which match 500 . Any suggestions?

Take advantage of 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. 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) . If the variable begin is not dereferenceable then this would be an error. 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).

Depending on the exact compilers you support, you may find enable_if as a builtin anyway- it's present in TR1.

However, the implementation of enable_if is trivial. You could simply copy it from Boost as well. 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:

// 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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