C++ Template Function Default Value

C++ template function default value

Try this:

template<class T> T sum(T a, T b, T c=T())
{
return a + b + c;
}

You can also put in T(5) if you are expecting an integral type and want the default value to be 5.

Data type of default value for template function argument different from instantiating data type

Shouldn't the Case 1 and Case 3 also fail, because the function
template is instantiated by int and the deafult value is of type
std::string?

No it shouldn't. See below for why. If you want it to fail then you should define f() to be a regular function receiving an argument of type std::string and not a function template.

What you have is a case of default argument instantiation, see here in [temp.inst]:

If a function template f is called in a way that requires a default
argument to be used, the dependent names are looked up, the semantics
constraints are checked, and the instantiation [...] is done as if the default argument had been an
initializer used in a function template specialization
, [...] This analysis is
called default argument instantiation. The instantiated default
argument is then used as the argument of f
.

When you write:

template <typename T>
void f(T x = std::string{""}){...}

it means that "" is the default argument for x only in case the call is made without any arguments. for example in your Case 2.

Your template function is defined to be instatiated just fine for either int or various other types.

For example here (Case 1):

f(23);

It is instatiated implicitly (by inference base on the argument type) to be f<int>(), as 23 is defined in the spec to be an int literal. The parameter x of type int receives the non-default value of 23 which you have provided at the call site.

And here (Case 2):

f<int>();

is exactly where the standard clause above comes into play: You successfully instantiate f() but no argument is provided for it, hence the instantiated default argument is then used as the argument of f. So compilation fails as this default value here for parameter x is defined to just be std::string and no conversion applies from it to type int. It is effectively equivalent to calling f("") on a function declared void f(int x).

And here (Case 3):

f<int>(23);

Explicit again and this time you provide the right type of argument at the call site.

Default value for template function argument

Yes, default value is not considered in template arugment deduction.

Type template parameter cannot be deduced from the type of a function default argument

You can add an overload, e.g.

template <typename T>
void myFunc(int value, T mode)
{
...
}
void myFunc(int value) {
myFunc(value, mode1());
}

Template default arguments

Note:

Foo me; without template arguments is legal as of C++17. See this answer: https://stackoverflow.com/a/50970942/539997.

Original answer applicable before C++17:

You have to do:

Foo<> me;

The template arguments must be present but you can leave them empty.

Think of it like a function foo with a single default argument. The expression foo won't call it, but foo() will. The argument syntax must still be there. This is consistent with that.

C++ function template using default parameters

Template parameters cannot be deduced from default arguments. C++11, [temp.deduct.type]§5:

The non-deduced contexts are:

  • ...
  • A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done.
  • ...

You can get around this using overloading:

template <typename Object, typename Comparator>
const Object &findMax(const vector<Object> &arr, const Comparator &isLessThan)
{
int maxIndex = 0;

for (int i = 1; i < arr.size(); i++) {
if (isLessThan(arr[maxIndex], arr[i])) {
maxIndex = i;
}
}
return arr[maxIndex];
}

template <typename Object>
const Object &findMax(const vector<Object> &arr)
{
return findMax(arr, std::less<Object>());
}

Default parameter value in template function, depending on type

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.

Default value for template with member function pointer

How do I make &Foo::DoNothing() the default for Func(...)?

You basically just specify the required default arguments:

struct Foo { int DoNothing() const { } };

template<
typename T,
typename C,
typename R = decltype(std::declval<const C>().DoNothing())
>
T Func(C const* obj,
R (C::*mf)() const = &C::DoNothing,
T* maybe_unused = nullptr)
{
(obj->*mf)();
return T{};
}

Note that you need to specify two different things: for one the default member function to call and additionally the default return value type, as it cannot be deduced from default arguments.

Default template parameter cannot be used inside another template parameter?

This:

DefaultType obj; 

uses CTAD (class template argument deduction) which is available since C++17 and only in certain contexts:

  • any declaration that specifies initialization of a variable and variable template
  • new-expressions
  • function-style cast expressions
  • the type of a non-type template parameter:

To instantiate DefaultType with the default argument in other contexts you still need to write DefaultType<>.

I suppose the reason to have CTAD only in certain contexts is that those are the contexts where you always want an instantiation, but never the template.



Related Topics



Leave a reply



Submit