Frage

I'm porting a project from MSVC to Borland C++ and I'm running into difficulties with template functions. For example, the following

void fn(const char *buffer)
{
  vector<string> output;
  boost::split(output, string(buffer), is_any_of(","));
  // ...

causes a compiler error:

[BCC32 Error] example.cpp(208): E2285 Could not find a match for 'split<SequenceSequenceT,RangeT,PredicateT>(vector<string,allocator<string> >,string,is_any_ofF<char>)'

whereas the modified example

void fn(const char *buffer)
{
  vector<string> output;
  string sBuffer(buffer);
  boost::split(output, sBuffer, is_any_of(","));
  // ...

compiles fine.

The generalization of this problem, as indicated in the post title, is that in certain cases BCC does not seem to match the template function if arguments are passed in as temporary objects that are constructed inside the function's argument list.

Before changing all the affected code, I'd like to understand why BCC thinks the first example is wrong. Is this a deficiency of the compiler, or does my code not comply to C++ standards?

I'm using RAD Studio / C++ Builder XE2.

War es hilfreich?

Lösung

It's not because the function is a template; it's because for some reason it takes its Input argument as a non-const lvalue reference, as documented here:

template<typename SequenceSequenceT, typename RangeT, typename PredicateT> 
  SequenceSequenceT & 
  split(SequenceSequenceT & Result, RangeT & Input, PredicateT Pred, 
        token_compress_mode_type eCompress = token_compress_off);

In standard C++, you can't bind a temporary rvalue, such as string(buffer), to such a reference. In Microsoft's imaginative reinterpretation of the language, you can.

The solution is to do exactly what you've done: introduce a named, non-temporary variable which can be passed by reference.

Andere Tipps

From the Boost manual

template<typename SequenceSequenceT, typename RangeT, typename PredicateT> 
  SequenceSequenceT & 
  split(SequenceSequenceT & Result, RangeT & Input, PredicateT Pred, 
        token_compress_mode_type eCompress = token_compress_off);

It seems like the function does indeed take its parameters by reference, so your "workaround" is actually the correct way of using it.

MSVC is known to allow binding to a non-const reference as an "extension".

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top