What are the uses of default function template arguments - c++11

Unlike the class template arguments, which have to be specified by the user of the template, the function template arguments are deduced by the compiler. Therefore, a natural question arises: why might one want to specify default function template arguments?
One usage I can come up with is when we want to force some of the function template arguments without needing to specify all of them. However, this seems to be a corner case. Are there other cases?

This might be a partial answer. One use I thought of is when we have a template parameter that does not appear as type in the function's parameter list and thus cannot be deduced. Providing a default argument for that template parameter might be very reasonable. The above comment by n.m. provides a good example of this usage.

Try to convert below func into the constructor( they dont have return type).
template<class T>
typename std::enable_if< std::is_fundamental<T>::value >::type func(T p_arg){}
template<class T>
typename std::enable_if< !std::is_fundamental<T>::value >::type func(T const &p_arg){}
Its pretty easy with default function template arguments.

Example:
template <typename Y, typename Y, int Z>
class Do{};
X,Y,Z are template parameters.
A user can use this like:
Do<int,int,1> doit;
While using a class template there is no way that template parameters get deduced from a function argument.
You call something "default" arguments...
template <typename Y, typename Y, int Z=9>
class Do{};
Here Z is defaulted to 9 if nothing was given from the using code like:
Do<int,int> doit;
And if your template arguments can be deduced from function arguments a user maybe want a special template instance to be used like:
template <typename T>
void func( const T&);
template<>
void func( const int& )
{
std::cout << "int in use" << std::endl;
}
template<>
void func( const double&)
{
std::cout << "double in use" << std::endl;
}
int main()
{
func(3.4); // calls double
func<int>(3.4); //calls int
}

Related

Store parameter pack as tuple references

I am trying to store the parameter pack of lvalue references of a variadic template for later use.
I have the following working for now.
template <typename... Ts>
class Foo {
private:
std::tuple<Ts...> m_args;
public:
template<typename... Args>
Foo(Args&&... args) : m_args(std::make_tuple(std::forward<Args>(args)...))
{
}
};
int main() {
int x = 10;
int y = 20;
Foo<int, int> foo(x, y);
}
However, I would like to store the parameter pack as a reference so that I can access the same object later.
I am not sure how I can do that. Any help would be appreciated.
The best I can imagine, is the use of std::forward_as_tuple.
Unfortunately I don't see a way to use it with perfect forwarding: if you want register values in a tuple inside a class, you have to decide the type of the tuple one time for all.
The best I can imagine is a tuple of const references; something as follows
template <typename ... Ts>
class Foo
{
private:
std::tuple<Ts const & ...> m_args;
public:
Foo (Ts const & ... as) : m_args{std::forward_as_tuple(as...)}
{ }
};
I hope isn't necessary remember you how dangling references can be dangerous for a solution based on a tuple of references.

How to make a particular constructor on a tempate type available only for a particular specialization in C++11?

I have a C++11 template that can be specialized with an arbitrary type parameter.
template<class ElementType>
class Foo
How do I declare a constructor that appears for the compiler's consideration only when ElementType is e.g. const uint8_t?
That is, I have a bunch of constructors that are generic over any ElementType, but I also want to have constructors that are only considered when ElementType is specialized in a particular way. (Allowing those constructors to be selected for other types would be unsafe.)
So far std::enable_if examples that I've found have been conditional on the types of the arguments of the constructors.
template<class ElementType>
struct Foo
{
template <typename T = ElementType>
Foo(typename std::enable_if<!std::is_same<T, const uint8_t>{}>::type* = nullptr) {}
template <typename T = ElementType>
Foo(typename std::enable_if<std::is_same<T, const uint8_t>{}>::type* = nullptr) {}
};
int main()
{
Foo<int> a{}; // ok, calls first constructor
Foo<const uint8_t> b{}; // ok, calls second constructor
}
wandbox example
You can break the class into two classes. The derived class' purpose is to be able to specialize constructors for different types. E.g.:
#include <cstdio>
#include <cstdint>
template<class ElementType>
struct Foo_
{
Foo_() { std::printf("%s\n", __PRETTY_FUNCTION__); }
};
template<class ElementType>
struct Foo : Foo_<ElementType>
{
using Foo_<ElementType>::Foo_; // Generic version.
};
template<>
struct Foo<uint8_t> : Foo_<uint8_t>
{
Foo() { std::printf("%s\n", __PRETTY_FUNCTION__); } // Specialization for uint8_t.
};
int main(int ac, char**) {
Foo<int8_t> a;
Foo<uint8_t> b;
}
The benefit of using the derived class here compared to enable_if is that:
The class can be partially specialized.
Only one specialization of the class is chosen for particular template parameters, rather than a set of constructors. When adding specializations for new types the existing enable_if expressions may need to be changed to make them more restrictive to avoid function overload set resolution ambiguity.

How can I "ostensibly-but-not-really" break the one-definition-rule with enable_if and SFINAE?

I want to define template <typename T> struct is_non_negative in one way for integral T's and another way for floating-point T's. Here's what I did:
template<typename T>
struct is_non_negative: public curry_right_hand_side<greater_equal<
typename std::enable_if<std::is_integral<T>::value, T>::type>, constant<T, 0>> { };
template<typename T>
struct is_non_negative: public curry_right_hand_side<greater_equal<
typename std::enable_if<std::is_floating_point<T>::value, T>::type>, constant_by_ratio<T, std::ratio<0,1>>> { };
This triggers a compiler error (GCC 4.9.3, -std=c++11):
error: class template "cuda::is_non_negative" has already been defined
and, well, it has, but it also hasn't, since the template instantiations are distinct.
How can I achieve this effect and actually get my code to compile?
Notes:
Never mind how I defined constant, constant_by_ratio and curry_right_hand_side - they have been tested and work.
If I replace the second is_non_negative with foo then this compiles and is usable - but not with the same identifier.
The motivation for the two definitions here is the impossibility of using floating-point values as template parameters, but please don't focus on that aspect of the example.
Maybe you could do something like this:
template<class T, class = void>
struct is_non_negative;
template<typename T>
struct is_non_negative<T, typename std::enable_if<std::is_integral<T>::value>::type>: public curry_right_hand_side<greater_equal<T>, constant<T, 0>> { };
template<typename T>
struct is_non_negative<T, typename std::enable_if<std::is_floating_point<T>::value>::type>: public curry_right_hand_side<greater_equal<T>, constant_by_ratio<T, std::ratio<0,1>>> { };

Possible to write the code once for a specific set of different types?

I have a template class TC who's constructor takes parameters who's values are dependent on, as well as being of type Tn.
So, I want to create a helper template function htf that will call the same functions of a Tn object to generate a TC for a set of types X0 to Xn. The helper function takes only one parameter from that set. Is it possible, perhaps with variadic templates, to write the function once for the set of types, instead of having to write the same function over and over again for each type?
Now, I could just use a template to allow all types, but I don't want that as there may be another function with the same name written for a specific type later that's not based on this TC. And, IIRC I think SFINAE works with member functions, not pure functions.
This is just an idea in my head at the moment, that's why the question is very general. However, here is roughly the code I'm thinking of, simplified, in an more concrete and in an over generalized fashion:
struct X0
{
int value;
int& fn() { return value; }
};
struct X1
{
double value;
double& fn() { return value; }
};
struct X2
{
float value;
float& fn() { return value; }
};
struct Y0 // don't accept this class in helper function
{
int value;
int& fn() { return value; }
};
template<typename T1, typename Tn>
class TC
{
T1* m_pT1;
Tn* m_pTn;
TC(T1* pT1, Tn* pTn) : m_pT1(pT1), m_pTn(pTn) {}
friend TC htf(Tn& tn);
public:
~TC() {}
};
// concrete functions:
TC<int, X0> htf(C0& x) { return TC<int, X0>(&x.fn(), &x); }
TC<double, X1> htf(C1& x) { return TC<double, X1>(&x.fn(), &x); }
TC<float, X2> htf(C2& x) { return TC<float, X2>(&x.fn(), &x); }
// or in an over generalized template function but it'll accept
// Y0 and others which I don't want:
template<typename X>
auto htf(X& x) -> TC<decltype(x.fn()), X>
{
return TC<decltype(x.fn()), X>(&x.fn(), &x);
}
So the htf function that I want is to work for classes X0, X1, and X2, but not Y0. However, I don't want it to interfere with any other function called htf that takes a parameter of type Y0, or any other type for that matter.
Additional
Is it possible to make it so that the collection of accepted classes can also include template classes taking an specified (or unspecified) number of parameters?
Write a function that is only enabled when a trait is true, then specialize it for all the desired types.
template<typename T>
struct enable_htf : std::false_type { };
template<>
struct enable_htf<X0> : std::true_type { };
template<>
struct enable_htf<X1> : std::true_type { };
// etc.
template<typename T, bool enable = enable_htf<T>::value>
struct htf_helper { };
template<typename T>
struct htf_helper<T, true>
{
using type = TC<decltype(std::declval<T&>().fn()), T>;
};
template<typename X>
typename htf_helper<X>::type
htf(X& x)
{
return { &x.fn(), &x };
}
But it seems you want something like this instead:
template<typename Needle, typename... Haystack>
struct is_one_of;
template<typename Needle, typename Head, typename... Tail>
struct is_one_of<Needle, Head, Tail...>
: conditional<is_same<Needle, Head>::value, true_type,
is_one_of<Needle, Tail...>>::type
{ };
template<typename Needle>
struct is_one_of<Needle> : false_type
{ };
template<typename X,
typename Requires = typename enable_if<is_one_of<X, X0, X1, X2>::value>::type>
auto
htf(X& x) -> TC<decltype(x.fn()), X>
{
return { &x.fn(), &x };
}
But personally I don't consider that clearer, even if is_one_of is reusable elsewhere.
This is an even more simplified version of my original question, but it relates to enabling a template function based on the type passed to it being part of a list of accepted types.
class A{};
class B{};
class C{};
class D{};
class collection1 : A, B, C {};
class collection2 : D {};
template<typename X>
typename std::enable_if<std::is_base_of<X, collection1>::value, X>::type fn(X x)
{
return X();
}
Then the following would work appropriately:
fn(A()); // works
fn(B()); // works
fn(C()); // works
fn(D()); // compile time failure
Having a 2nd function like this:
template<typename X>
typename std::enable_if<std::is_base_of<X, collection2>::value, X>::type fn(X x)
{
return X();
}
Would result in:
fn(A()); // works
fn(B()); // works
fn(C()); // works
fn(D()); // works
Using this method, I can enable function fn to work with types I want and not others and I can write the list with ease. Also, this should be faster than iterating through a list of variadic template parameters.
Thanks Jonathan Wakely, you helped a lot in my thought process. I just thought that this is simpler and can be made even clearer if I use a helper template which would encapsulate the enable_if clause which would be good as I have many other functions that would require this.
Additional
Looks like this answer isn't good enough as I need to be able to determine if a template class is in the collection I'm looking for.

Explicit function template specialization

I thought that template specializations were fully independent entities and could have whatever they wanted. But VC++ threw me an error when I made the return type of a specialization different to the return type of the original template. Is that really Standard? I worked around it easily by moving the function body into a static class.
There is no function template partial specialization, because there's overloading of functions (and function templates. However, function overloading is much more limited than template specialization, so what you usually do, is to fall back on class template specializations:
template< typename R, typename T >
struct foo_impl {
static R foo(T)
{
// ...
return R(); // blah
}
};
template< typename T >
struct foo_impl<void,T> {
static void foo(T)
{
// ...
}
};
template< typename R, typename T >
R foo(T obj);
{
return foo_impl<R,T>::foo(obj); // fine even if R is void
}
Function specialization is weird and almost non-existent. It's possible to fully specialize a function, while retaining all types - i.e. you're providing a custom implementation of some specialization of the existing function. You can not partially specialize a templated function.
It's likely that what you're trying to do can be achieved with overloading, i.e.:
template <typename T> T foo(T arg) { return T(); }
float foo(int arg) { return 1.f; }

Resources