Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default parameter value in template function, depending on type

Tags:

c++

templates

Suppose I have this function to trim an std::string and decide to extend it, so that it removes not only spaces from the beginning and end, but also any character I pass in another string, like spaces, newlines and carriage returns.

std::string Trim ( const std::string &In_Original,
  const std::string &In_CharsToTrim = " \n\r" );

So basically, it would remove all characters present in In_CharsToTrim from the beginning and end of In_Original.

Now, I had to write this for both std::string and std::wstring. Since I find that absurd, I chose to make use of templates, and it works, but I am unable to pass a default value, because the std::wstring version must get L" \n\r" as the default value (note that little L, there).

I tried this:

template <typename Type> Type Trim ( const Type &In_String,
  const Type &In_TrimCharacters );

along with:

template std::string Trim ( const  std::string &In_String,
  const  std::string &In_TrimCharacters = " \n\r" );
template std::wstring Trim ( const  std::wstring &In_String,
  const  std::wstring &In_TrimCharacters = L" \n\r" );

But it didn't work. It doesn't even compile.

Currently, what I have, is a separate function for when you call without a second parameter, but this is completely the wrong approach:

template <typename Type> Type Trim ( const Type &In_String,
  const Type &In_TrimCharacters );
std::string Trim ( const std::string &In_String );
std::wstring Trim ( const std::wstring &In_String );

Then, in this simpler Trim function, I'm simply calling the complete version.

So, basically, what I'm asking is this...:

How can I pass a different default value depending on the template type? Basically, a specialization, in which the only change is the default parameter...

In this case, to pass std::string ( " \n\r" ) in one case, and std::wstring ( L" \n\r" ) in the other...

Or... is there another way to do what I'm trying to do, here?

like image 256
Joao Pincho Avatar asked Jul 11 '14 15:07

Joao Pincho


People also ask

Can we specify default value for template arguments?

Like function default arguments, templates can also have default arguments. For example, in the following program, the second parameter U has the default value as char.

Can default argument be used with the template class?

Can default arguments be used with the template class? Explanation: The template class can use default arguments.

Can we use non-type parameters as argument templates?

A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.

How will you restrict the template for a specific datatype?

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.


1 Answers

This is what I come up with:

template <typename T> struct default_trim_chars;

template<> struct default_trim_chars<std::string> { 
    static const char* value() { return " \n\r"; }
};

template<> struct default_trim_chars<std::wstring> { 
    static const wchar_t* value() { return L" \n\r"; }
};

template <typename Type> Type Trim ( const Type &In_String,
const Type &In_TrimCharacters = default_trim_chars<Type>::value()){
    /* ... */
}

You can also declare value as a data member instead of a function, but that would require constexpr and C++11.

like image 162
T.C. Avatar answered Oct 01 '22 08:10

T.C.