2

I am using boost::program_options and want to pass "domain"-like options to my program. Such a domain is simply:

template<typename T>
struct CDomain
{
  CDomain(T min = -1, T max = 1) {_min = min; _max = max;};
  T _min;
  T _max;
};

I have written a custom validator for this option class and that works well. Now as I wanted to add a default value, as in

desc.add_options()("domain", po::value<CDomain<long double> >()->default_value(CDomain<long double>(-1,1)), "domain");

boost::program_options called for an operator<<:

error: no match for ‘operator<<’ in ‘stream << input’

I added this one, but still get the same error message:

template<typename T>
ostream& operator<<(ostream& o, CDomain<T>& d)
{
  return o << "[" << boost::lexical_cast<string>(d._min) << ":" << boost::lexical_cast<string>(d._max) << "]";
}

How can I define operator<< for use with default value output in custom option descriptions?


I did some more investigation. The error occurs in boost/lexical_cast.hpp:1147 In member function bool boost::detail::lexical_stream_limited_src<CharT, Traits, RequiresStringbuffer>::shl_input_streamable(InputStreamable&) [with InputStreamable = const CDomain<long double>, CharT = char, Traits = std::char_traits<char>, bool RequiresStringbuffer = true]:

template<typename InputStreamable>
bool shl_input_streamable(InputStreamable& input)
{
    std::basic_ostream<CharT> stream(&stringbuffer);
    bool const result = !(stream << input).fail();
    start = stringbuffer.pbase();
    finish = stringbuffer.pptr();
    return result && (start != finish);
}

This might be a namespace issue, but moving ostream& operator<<(ostream& o, CDomain<T>& d) into boost::detail didn't solve the problem.

Christoph
  • 1,040
  • 3
  • 14
  • 29

1 Answers1

2

Redefine your structure likewise:

template<typename T>
struct CDomain
{
  CDomain(T min = -1, T max = 1) {_min = min; _max = max;};
  T _min;
  T _max;

  friend std::ostream& operator << (std::ostream& s, const CDomain& domain)
  {
    so << "[" << boost::lexical_cast<string>(d._min) << ":" << boost::lexical_cast<string>(d._max) << "]"
    return s;
  }
};

That should fix the issue I believe. Here I see it working (Modifed version to make it work online).

Vite Falcon
  • 6,575
  • 3
  • 30
  • 48
  • The operator works as I have defined it - I can call use it whereever I want. The problem is that boost wants operator<<, but doesn't find mine. – Christoph Mar 02 '12 at 11:33
  • Have you tried it this way to see if it makes any difference? And where did you define your `operator <<` function? Was it defined before where you wanted boost to use it? – Vite Falcon Mar 02 '12 at 12:24
  • I've tried it without success first, but now wrote minimal code to test it again and everything was well. Thank you! I just don't understand why the non-friend out-of-class operator<< didn't work... – Christoph Mar 02 '12 at 12:31
  • My best guess is that you probably didn't define it prior to where boost actually needs it, which would probably be in one of its header files. There a change in the order of includes could've made this differences. – Vite Falcon Mar 02 '12 at 12:48