Is there a way to create a c++ template with different return types?

Viewed 107

I'm wondering if there's a way to write a C++ template with different return types.

My use case is a method returning the largest values from a list.

But since I'm using the Qt framework, this function shall be able to deal with numeric and QString values. When feeding this function with a list of QString, the function shall return the length of the largest string. In case of passing numeric values, the input type shall be the return type.

What I've written is this:

template< class T >
auto getMax( QList< T > aList ) -> decltype( std::is_arithmetic< T >::value ? T : int( 0 ) )
{
  if ( std::is_arithmetic< T >::value )
  {
      T Result( aList.isEmpty() ? 0 : aList.first() );
      for ( auto lElement : aList )
      {
          Result = std::max( Result, lElement );
      }

      return Result;
  }

  if ( std::is_same< T, QString >::value )
  {
      // List contains QString -> return length of largest string
      int Result( aList.isEmpty() ? 0 : aList.first().length() );

      for ( const QString & lrcsElement : aList )
      {
          Result = std::max( lrcsElement.length(), Result );
      }

      return Result;
  }

  return 0;
}

This code compiles with VS 2017.

But when I want to use the template function like this

const QString sError  ( tr( "Error"       ) );
const QString sWarning( tr( "Warning"     ) );
const QString sInfo   ( tr( "Information" ) );
const QString sDebug  ( tr( "Debug "      ) );
auto iMaxTextLength( SMUtils::getMax< QString >( { sError, sWarning, sInfo, sDebug } ) );

the compiler gives me some error messages:

  • Error C2672: "SMUtils::getMax": no matching overloaded function found.
  • Error C2893: Failed to specialize function template "unknown-type SMUtils::getMax(QList)".
  • Error C2119: "li32MaxTextLength": the type for "auto" cannot be deduced from an empty initializer.

Of course I could write a specialized getMax( QStringList ) method, but I was wondering if it's possible to use only one template function.

Is that even possible and if so, how?

Thanks, Sören

1 Answers

-> decltype( std::is_arithmetic< T >::value ? T : int( 0 ) )

should be

-> std::conditional_t<std::is_arithmetic<T>::value, T, int>;

or even omit it completely and let compiler deduce it (but requires correct return types, so following if constexpr).

and your

if ( std::is_arithmetic< T >::value )

should be

if constexpr ( std::is_arithmetic< T >::value )
Related