Explicit function template specialization - c++11

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; }

Related

Ambiguous access error when accessing base class functions while inheriting from variadic template

I am trying to create class deriving from variadic template. Here is the code:
struct Some { };
template < class Base, class T >
struct Feature
{
protected:
void DoStuff(T& t) { }
};
template < class T, class ... Ts >
struct MultiFeature
: public Feature< T, Ts >...
{
};
class TestFeature
: public MultiFeature< Some, std::int16_t, std::string >
{
public:
void TestDoStuff()
{
std::int16_t i;
DoStuff(i);
}
};
Feature should be a simple wrapper around some basic type (in this case, integer and string), providing some functionality to class deriving from it. MultiFeature is used so that I do not have to derive from Feature< std::int16_t >, Feature< std::string >.
As far as I understand, there should be no ambiguity in this case, because there are two different DoStuff functions, each taking different parameter type, however VS2017 complains about ambiguous access. Is this correct behavior? If so, is there any simple workaround around this problem?
EDIT
It seems that compiler is right here, however in this answer, suggested workaround for this is to bring base class member functions into scope with using (Ambiguous access to base class template member function). Is it somehow possible to do this for variadic template base class?
It seems that compiler is right here, however in this answer, suggested workaround for this is to bring base class member functions into scope with using (Ambiguous access to base class template member function). Is it somehow possible to do this for variadic template base class?
If you can use C++17, it's trivially simple
template <typename T, typename ... Ts>
struct MultiFeature : public Feature<T, Ts>...
{
using Feature<T, Ts>::DoStuff...;
};
Unfortunately the variadic using is introduced in C++17 so, in C++11 and C++14, the best I can imagine is a MultiFeature recursive definition
// ground case: a fake DoStuff to abilitate following using
template <typename T, typename ... Ts>
struct MultiFeature
{ void DoStuff () { } };
// recursion case
template <typename T, typename T0, typename ... Ts>
struct MultiFeature<T, T0, Ts...>
: public Feature<T, T0>, public MultiFeature<T, Ts...>
{
using Feature<T, T0>::DoStuff;
using MultiFeature<T, Ts...>::DoStuff;
};
The following is a full compiling example (with both cases)
struct Some { };
template <typename, typename T>
struct Feature
{
protected:
void DoStuff (T &) { }
};
#if 0
template <typename T, typename ... Ts>
struct MultiFeature : public Feature<T, Ts>...
{
using Feature<T, Ts>::DoStuff...;
};
#else
// ground case: a fake DoStuff to abilitate following using
template <typename T, typename ... Ts>
struct MultiFeature
{ void DoStuff () { } };
// recursion case
template <typename T, typename T0, typename ... Ts>
struct MultiFeature<T, T0, Ts...>
: public Feature<T, T0>, public MultiFeature<T, Ts...>
{
using Feature<T, T0>::DoStuff;
using MultiFeature<T, Ts...>::DoStuff;
};
#endif
struct TestFeature
: public MultiFeature<Some, short, int, long, long long>
{
void TestDoStuff ()
{ int a{}; DoStuff(a); }
};
int main ()
{
TestFeature tf;
}

Can i use 2 different functions returning different data types inside my template function code?

I am trying to templatize some of my code and am not sure if i am doing it correct way ?
template <typename T>
class User
{
public:
template <typename T>
void foo() {
A* pa = funcA();
OR
B* pb = funcB();
//common code follows
....
....
....
};
User<Atype> C1;
User<Btype> C2;
In the above code I am looking as to how to define foo() as to be able to use
either of A* pa = funcA() or B* pb = funcB() based on how the class is instantiated. C1 should be able to use A* pa = funcA() and C2 should be able to use B* pb = funcB().
Not directly, but there is various options. Normally it is best to avoid designs that result in needing different named functions, or conceptually different operations.
For example if both A and B had a member or static function foo, then you could call that (x.foo(), T::foo(), etc.) instead of having the separately named funcA and funcB. Or similarly, in the case of parameters you can use function overloading (as you can't overload on the return type), such as std::to_string, and sometimes using templates as well such as std::swap.
Otherwise, if you need to support completely different things, then there are many options.
You can specialise foo to have different implementations for different types. This is often not particularly ideal if you are planning to use many different types with a template function or class. In some cases you might specialise the entire class, and there is also partial specialisation.
class A {};
class B {};
A *funcA();
B *funcB();
template <typename T>
class User
{
public:
void foo();
};
template<> void User<A>::foo()
{
auto a = funcA();
// ...
}
template<> void User<B>::foo()
{
auto ab = funcB();
// ...
}
Similar to 1, you can have a separate template function or class that is specialised.
class A {};
class B {};
A *funcA();
B *funcB();
template<class T> T *funcGeneric();
template<> A *funcGeneric<A>() { return funcA(); }
template<> B *funcGeneric<B>() { return funcB(); }
template <typename T>
class User
{
public:
void foo()
{
auto p = funcGeneric<T>();
}
};
Or with a class, which can be useful if you have multiple methods or pieces of information. For a single method, the call operator is often overloaded.
template<class T> class FuncGeneric;
template<> class FuncGeneric<A>
{
public:
A *operator()()const { return funcA(); }
};
template<> class FuncGeneric<B>
{
public:
B *operator()()const { return funcB(); }
};
template <typename T>
class User
{
public:
void foo()
{
auto p = FuncGeneric<T>()();
}
};
Extending on 2, but you pass the "adapter" as a template parameter itself. This is one you see in the STL a fair bit, with things like std::map taking the Compare parameter (default std::less), unique_ptr taking a deleter (with std::default_delete calling delete), hash functions, etc.
template<class T> class FuncGeneric;
template<> class FuncGeneric<A>
{
public:
A *operator()()const { return funcA(); }
};
template<> class FuncGeneric<B>
{
public:
B *operator()()const { return funcB(); }
};
template <class T, class Func = FuncGeneric<T>>
class User
{
public:
void foo()
{
auto p = Func()();
}
};
In some cases you might pass the function itself. More common for functions rather than classes, for example many of the algorithms (e.g. find_if) do this.
template <class T, class Func>
class User
{
public:
User(Func func) : func(func) {}
void foo()
{
auto p = func();
}
private:
Func func;
};
int main()
{
User<A, A*(*)()> user(&funcA);
}
Functions can also be a template parameter themselves, although this is fairly uncommon.
template <class T, T*(*Func)()>
class User
{
public:
void foo()
{
auto p = Func();
}
};
int main()
{
User<A, &funcA> user;
}

Pointers to member as variadic template parameters

Is it possible to pass pointers-to-member as variadic template arguments. I can't seem to figure out the syntax.
for a function call it works like this:
struct A
{
int a;
float b;
}
template <typename ... TArgs> void f(A *obj, TArgs ... params)
{
void *members[] { (&(obj->*params))... };
// ... do something ...
}
That can be used like this:
f(obj, &A::a, &A::b);
I would like to pass params in a similar fashion to a class template
template <[something] ... params> class Foo
{
void Bar(A *obj)
{
void *members[] { (&(obj->*params))... };
// ... do something ...
}
};
That should be used like this:
Foo<&A::a, &A::b> foo;
foo.bar(obj);
I'm having trouble figuring out what [something] should be.
If member type is known and there is only one parameter, it can be done like this:
template <int A::*ptr> //...
Is there a way to generalize this for variadic parameter list of member pointers where members are of different unknown beforehand types?
Update: Variadic argument pack for member pointers of fixed known types is declared like so:
template<int A::*...ptr> struct Foo {};
Now I just need to replace int with typename that can be deduced.
And with C++17, following works perfectly:
template<auto A::*...ptr> struct Foo {};
Unfortunately I need a solution that will work with C++14
In C++14, you can use another level of indirection to do that:
struct A {
int a;
float b;
};
template<typename... T>
struct Bar {
template <T A::*... params>
struct Foo {
void Bar(A *obj) {
void *members[] { (&(obj->*params))... };
// ... do something ...
(void)members;
}
};
};
int main() {
A a;
Bar<int, float>::Foo<&A::a, &A::b> foo;
foo.Bar(&a);
}
auto keyword (introduced with the C++17 for non-type template parameters, as you mentioned) solves more or less this kind of issues. Think of std::integral_constant and how would it be more user-friendly if you hadn't to specify each time the type as the first argument...

What are the uses of default function template arguments

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
}

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.

Resources