tags:

views:

45

answers:

1

To be consistent with other classes in a library, my array class below has two read() methods. The first reads the entire array to an output iterator and returns an error code, the second reads a single value and returns that (using exceptions for errors).

The problem I have is that if I call the second read(size_t idx) method with an int, the compiler prefers the templated method. I need to explicitly specify an unsigned int to make it work. My question is, what are my options around this problem:

  • Rename either read function to avoid overloading
  • Use something like boost::enable_if to prevent the iterator version from working with non-iterators. This sullies the interface though...
  • Any other ideas that I'm missing?

-------------------------------------------------------------

#include <iostream>
#include <iterator>
#include <vector>

struct FooArray
{
  template <typename TIter>
  int read( TIter out )
  {    
    *out++ = 123.456; // copy stuff to output iterator
    return 99;        // error code
  }

  double read( size_t index )
  {    
    return 1.234; // return value at index
  }
};

int main(int argc, char**argv)
{
  FooArray tmp;
  std::cout << tmp.read(10u) << std::endl;
  /* std::cout << tmp.read(10) << std::endl;   COMPILER ERROR */
  tmp.read( std::ostream_iterator<double>(std::cout,"\n") ); 
}
+1  A: 

Furthermore, I don't think size_t is guaranteed to be a synonym for unsigned, so even with the "u" suffix the code might not be portable.

std::string has a similar problem that it has to distinguish between:

string s(10, 97);  //size_t, char
string t(s.begin(), s.end()); //iter

That would internally forward the call to a suitable helper function (needs a compiler-time test somewhere if the arguments are integral).

However, in your case, the return types are different as well, therefore you'll have to select the correct overload to begin with.

It won't look that bad with enable_if:

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>

struct FooArray
{
  template <typename TIter>
  typename boost::disable_if<boost::is_integral<TIter>, int>::type
       read( TIter out )
  {
    *out++ = 123.456; // copy stuff to output iterator
    return 99;        // error code
  }

  double read( size_t index )
  {
    return 1.234; // return value at index
  }
};
UncleBens
+1, exactly what I wanted to write before actually reading your answer xD
Johannes Schaub - litb
Thanks for confirming what I thought. I'll give the enable_if method a go and see if my template-phobic colleagues complain!
Brian O'Kennedy