Function template specialization with overloads with different number of parameters - c++

Consider the following (invalid) code sample:
// a: base template for function with only one parameter
template<typename T>
void f(T t) { }
// b: base tempalte for function with two parameters
template<typename T1, typename T2>
void f(T1 t1, T2 t2) { }
// c: specialization of a for T = int
template<>
void f<int>(int i) { }
// d: specialization for b with T1 = int - INVALID
template<typename T2>
void f<int, T2>(int i, T2 t2) { }
int main() {
f(true); // should call a
f(true, false); // should call b
f(1); // should call c
f(1, false); // should call d
}
I've read this walk-through on why, in general, partial function template specializations won't work, and I think I understand the basic reasoning: there are cases where function template specializations and overloading would make certain calls ambiguous (there are good examples in the article).
However, is there a reason why this specific example wouldn't work, other than "the standard says it shouldn't"? Does anything change if I can guarantee (e.g. with a static_assert) that the base template is never instantiated? Is there any other way to achieve the same effect?
What I actually want to achieve is to create an extendable factory method
template<typename T>
T create();
which also has a few overloads taking input parameters, e.g.
template<typename T, typename TIn>
T create(TIn in);
template<typename T, typename TIn1, typename TIn2>
T create(TIn1 in1, TIn2 in2);
In order to ensure that all necessary factory methods are present, I use static_assert in the function base templates, so that a compiler error is generated if the create method is called with template arguments for which no specialization has been provided.
I want these to be function templates rather than class templates because there will be quite a lot of them, and they will all use input from the same struct hierarchy, so instantiating 10 factories instead of one comes with some overhead that I'd like to avoid (not considering the fact that the code gets much easier to understand this way, if I can just get it to work...).
Is there a way to get around the problem outlined in the first half of this post, in order to achieve what I've tried to get at with the second half?
In response to iavr:
I could do this with plain overloading, which would (given the templates above) give something like
template<typename TIn2>
A create(bool, TIn2);
template<typename TIn2>
A create(int, TIn2);
if I need two different partial specializations with T = A, TIn1 specified and TIn2 still unspecified. This is a problem, since I have some cases (which are really text-book cases for meta-programming and templates) where I know that, for example, one of the arguments will be a std::string, and the other will be of some type that has a property fields and a property grids, which are of types std::vector<field> and std::vector<grid> respectively. I don't know all the types that will ever be supplied as the second argument - I know for sure that there will be more of them than the ones I currently have implemented - but the implementation of the method will be exactly the same.
While writing up this update, I think I've figured out a way to redesign the implementations so that there is no need for the partial specialization - basically, I do the following to cover the case outlined above:
template<>
A create<A, std::vector<field>, std::vector<grid>>(std::vector<field> fs, std::vector<grid> gs);
and then I have to change the calling signature slightly, but that's OK.

I share your concerns that maybe in this particular case there would be no problem having function template partial specializations, but then again, that's the way it is, so what would be your problem using plain overloading?
// a: base template for function with only one parameter
template<typename T>
void f(T t) { }
// b: base template for function with two parameters
template<typename T1, typename T2>
void f(T1 t1, T2 t2) { }
// c: specialization of a for T = int
void f(int i) { }
// d: specialization for b with T1 = int
template<typename T2>
void f(int i, T2 t2) { }
This also takes less typing and I get this is why you don't want to use function objects (which would have partial specialization).

Here is a simple workaround using a class template specialization:
template <typename, typename...>
struct Creator;
template <typename T, typename TIn>
struct Creator<T, TIn>
{
T call(TIn in)
{
// ...
}
};
template<typename T, typename TIn1, typename TIn2>
struct Creator<T, TIn1, TIn2>
{
T call(TIn1 in1, TIn2 in2)
{
// ...
}
};
template <typename R, typename... Arguments>
R Create(Arguments&&... arguments)
{
return Creator<R, Arguments...>::call(std::forward<Arguments>(arguments)...);
}

If you don't want overloading, and want to be able to specialize from a separate file, then I think you should base it on the solution on the link from your question. It involves making a static method on a class that you specialize. From my reading of the question, you're only interested in specializing on the T, not on the number of arguments, which you intend to forward. In C++11, you can do the following:
#include <iostream>
#include <utility>
using namespace std;
template<typename T>
struct factory_impl;
// Left unspecified for now (which causes compliation failure if
// not later specialized
template<typename T, typename... Args>
T create(Args&&... args)
{
return factory_impl<T>::create(std::forward<Args>(args)...);
}
// Note, this can be specified in a header in another translation
// unit. The only requirement is that the specialization
// be defined prior to calling create with the correct value
// of T
template<>
struct factory_impl<int>
{
// int can be constructed with 0 arguments or 1 argument
static int create(int src = 0)
{
return src;
}
};
int main(int argc, char** argv)
{
int i = create<int>();
int j = create<int>(5);
// double d = create<double>(); // Fails to compile
std::cout << i << " " << j << std::endl;
return 0;
}
Live example http://ideone.com/7a3uRZ
Edit: In response to your question, you could also make create a member function of a class, and pass along some of that data with the call or take action before or after
struct MyFactory
{
template<typename T, typename... Args>
T create(Args&&... args)
{
T ret = factory_impl<T>::create(data, std::forward<Args>(args)...);
// do something with ret
return ret;
}
Foo data; // Example
};

Related

Extract types from std::tuple for a method signature

I am looking for a way to extract the types of an std::tuple to define a method signature. Take the following (contrived) example:
template <typename RetT, typename... ArgsT>
class A
{
public:
typedef RetT ReturnType;
typedef std::tuple<ArgsT...> ArgTypes;
RetT doSomething(ArgsT... args)
{
// Doesn't make much sense, but it's just an example
return (RetT) printf(args...);
}
};
template <typename Enable, typename RetT, typename... ArgsT>
class AAdapter;
// Simply pass arguments along as-is
template <typename RetT, typename... ArgsT>
class AAdapter<std::enable_if_t<!std::is_same_v<RetT, float>>, RetT, ArgsT...> : public A<RetT, ArgsT...> {};
// Add additional first argument if RetT is float
template <typename RetT, typename... ArgsT>
class AAdapter<std::enable_if_t<std::is_same_v<RetT, float>>, RetT, ArgsT...> : public A<RetT, const char*, ArgsT...> {};
template <typename RetT, typename... ArgsT>
class B
{
public:
typedef AAdapter<void, RetT, ArgsT...> AAdapter;
// This needs to have the same method signature (return type and argument types) as AAdapter::doSomething()
template <size_t... Index>
typename AAdapter::ReturnType doSomething (
typename std::tuple_element<Index, typename AAdapter::ArgTypes>::type... args
) {
return a.doSomething(args...);
}
public:
AAdapter a;
};
int main(int argc, char** argv)
{
// I would like to be able to remove the <0,1,2> and <0,1,2,3> below.
B<int, const char*, int, int> b1;
b1.doSomething<0,1,2>("Two values: %d, %d\n", 1, 2);
B<float, const char*, int, int> b2;
b2.doSomething<0,1,2,3>("Three values: %s, %d, %d\n", "a string", 1, 2);
return 0;
}
Consider the way in which AAdapter changes, adds or removes argument types opaque. Basically, I want B::doSomething() to simply redirect to B::AAdapter::doSomething(), so I want both of these methods to have the exact same signature. The question is: How do I get the argument types of B::AAdapter::doSomething() from inside B?
My definition of B::doSomething() in the code above is the furthest I have come: I'm typedef'ing an std::tuple with the argument types inside A, so I can unpack them back to a parameter pack in B. Unfortunately, with the approach above I still need to provide the Index... template parameters manually when calling B::doSomething(). Surely there must be a way to have these Index... parameters automatically deduced from the size of the tuple. I have thought about approaches using std::make_integer_sequence, but that would require me to define an additional method argument for the sequence itself (and it can't be the last argument with a default value because no other arguments are allowed after a parameter pack).
Is there any way I can do this, with or without std::tuple? Solutions that require C++17 will be fine.
EDIT 1:
I realize now that I could probably circumvent the problem in my particular application by having B inherit from AAdapter instead of having an AAdapter object as a member, but I would still like to know how to solve the problem without having to do that.
EDIT 2:
Maybe some additional info on why AAdapter exists and what I want to achieve. I am implementing a kind of wrapper class around an existing C API that actually needs to be called in another process, RPC-style. So if the user wants to call a C function in the remote process, they will instead call a corresponding method in my wrapper class locally that handles all the RPC stuff like type conversions, the actual remote call and other ugly details. This wrapper class is represented by B in my code above. Now my wrapper method signature will usually not have the exact same signature as the C function. For example, the wrapper may have std::string_view instead of a pair of const char*, size_t that the C function has. For reasons that are not important here, it also needs to have an output parameter (a pointer) where the C function has a return value instead sometimes.
In order for me to not have to define two separate method signatures (in actuality it is three) and write code to convert the parameters for every single one, I instead pass only one of the signatures as template parameters RetT, ArgsT... to B. A signature conversion class (AAdapter in the example above) then applies rules for how to generate the second signature automatically from this first one by adding parameters, changing their types, etc.. A would then hold this generated signature, and B would have the one I provided initially. However, I want B to provide an invoke() method with the signature of A, thus hiding A and the entire method signature mess from the user completely. This is why I need access to the template parameter types of A from within B, and why I can't simply remove the middle class AAdapter.
The core of your problem is turning a tuple into an argument pack.
maybe the tuple type is not the template arguments? in this case, there is a simple solution by inheritance:
#include <vector>
#include <iostream>
#include <tuple>
template<typename... Types>
struct BImpl{
typedef std::tuple<std::vector<Types>...> tuple_type;
// maybe you will get a tuple type from some class templates. assume the 'tuple_type' is the result.
// requirement: 'tuple_type' = std::tuple<SomeTypes...>
// requirement: 'tuple_type' can be deduced definitely from template arguments 'Types...'.
template<typename> // you can add other template arguments, even another std::tuple.
struct OptCallHelper;
template<typename... Args>
struct OptCallHelper<std::tuple<Args...>>{
auto dosomething(Args&&... args) /* const? noexcept? */{
// do what you want...
// requirement: you can definitely define the 'dosomething' here without any other informations.
std::cout << "implement it here." << std::endl;
}
};
typedef OptCallHelper<tuple_type> OptCall;
};
template<typename... Types>
struct B : private BImpl<Types...>::OptCall{
typedef typename BImpl<Types...>::OptCall base;
using base::dosomething;
// obviously, you can't change the implementation here.
// in other words, the definition of 'dosomething' can only depend on template arguments 'Types...'.
};
int main(){
B<int, float> b;
b({}, {}); // shows "implement it here."
return 0;
}
you can do what you want to do in BImpl and then use B instead.
// This needs to have the same method signature (return type and argument types) as AAdapter::doSomething()
template <size_t... Index>
typename AAdapter::ReturnType doSomething (
typename std::tuple_element<Index, typename AAdapter::ArgTypes>::type... args
) {
return a.doSomething(args...);
}
for AAdaptor, I think you just want the interface of dosomething in A, and you can deduce it:
#include <iostream>
template<typename...>
struct AAdaptor{
int dosomething(){
std::cout << "???" << std::endl;
return 0;
}
};
// ignore the implementation of AAdaptor and A.
// just consider of how to get the interface of 'dosomething'.
template<typename... Types>
struct BImpl{
typedef AAdaptor<Types...> value_type;
typedef decltype(&value_type::dosomething) function_type;
// attention: it won't work if 'AAdaptor::dosomething' is function template or overloaded.
// in this case, you should let A or AAdaptor give a lot of tuples to declare 'dosomething', referring to the first solution.
template<typename>
struct OptCallHelper;
template<typename Ret, typename Klass, typename... Args>
struct OptCallHelper<Ret(Klass::*)(Args...)>{
value_type data;
Ret dosomething(Args... args){
return data.dosomething(args...);
}
};
// attention: 'Ret(Klass::*)(Args...)' is different from 'Ret(Klass::*)(Args...) const', 'noexcept' as well in C++17.
// even Ret(Klass::*)(Args..., ...) is also different from them.
// you have to specialize all of them.
typedef OptCallHelper<function_type> OptCall;
};
template<typename... Types>
struct B : BImpl<Types...>::OptCall{
typedef typename BImpl<Types...>::OptCall base;
using base::dosomething;
};
int main(){
B<int, float> b;
b(); // shows "???"
return 0;
}
if there is some difference between this code and your requirement, try to give another example to imply some of your implementation. it's still not clear what B gets and should do.
This demonstrates how you can get a function with the argument types from a tuple:
#include <iostream>
#include <tuple>
#include <utility>
template <
typename ArgTuple
>
class B_Class {};
template <typename... ArgTypes>
class B_Class<std::tuple<ArgTypes...> > {
public:
static void b(
ArgTypes...
) {
std::cout << "successful call" << std::endl;
}
};
int main() {
using ArgTypes = std::tuple<int, char, float, double>;
int i; char c; float f; double d;
B_Class<ArgTypes>::b(i, c, f, d);
}
This compiles and prints "successful call" when run.

Call less constrained functionally equivalent function

Consider the following code:
#include <iostream>
#include <type_traits>
struct A;
template<class T>
concept HasParent = std::is_convertible_v<typename T::parent*, A*>;
struct A{};
struct B : A { using parent = A; };
template<class T> int foo(T*) { return 1; }
template<HasParent T> int foo(T*)
{
// call the other one?
return 2;
}
int main()
{
B b;
std::cout << foo(&b) << std::endl; // displays 2
return 0;
}
Is it possible to call the general foo<T>(T*) function from foo<HasParent T>(T*)?
(this is a (functional) example, but I can link the complete code on github)
Is it possible to call the general foo<T>(T*) function from foo<HasParent T>(T*)?
You need some way to differentiate between the two functions in order to do this.
For example:
template <typename T> void foo(T);
template <typename T> requires true auto foo(T) -> int;
The second one is obviously more constrained than the first, for all T, so foo(42) calls the second. But, you can differentiate between the two:
auto unconstrained = static_cast<void(*)(int)>(foo);
Here, the constrained function template returns int so it's not a viable candidate and we get the unconstrained one instead.
In your example, both return int, so this particular trick doesn't work. But the key is that you need some way to differentiate the two templates.
A better way is probably:
template <typename T, std::monostate M = {}>
void foo(T);
template <typename T> requires true
void foo(T arg) {
foo<T, std::monostate{}>(arg); // calls the unconstrained one
}
Using monostate here is kinda cute since it doesn't actually change the number of template instantiations (there's only one monostate... ). foo(42) calls the second, which calls the first. Demo.
But it might be better to just add a new function and have both the unconstrained and constrained version of the function template invoke that one (in the sense that it's arguably less cryptic than the monostate approach).

select method code depending on template value

I've got a template c++ object as follows
template <typename T, Dimension D>
class Field : public std::vector<T>
{
// ... lot of stuff ...
T differentiate(const gridPoint<D>&, int) const;
};
This differentiate methode is computed differently depending of the Dimension D
enum Dimension : std::size_t { _2D = 2, _3D = 3 };
I could just put a switch inside the method's body bt I'd like to use the templates in order to help with clarity
I tried using std::enable_if like this:
template <typename T, Dimension D>
typename std::enable_if<D==_2D, T>::type
Field<T,D>::differentiate(const gridPoint<D>& pt, int extent) const
{
// ... lot of computation
}
template <typename T, Dimension D>
typename std::enable_if<D==_3D, T>::type
Field<T,D>::differentiate(const gridPoint<D>& pt, int extent) const
{
// ... even more computation
}
but the compiler tels me that my implementation doesn't match any prototypes
What did I do wrong ? I just can't figure out how i'm suppose to declare the method's code
You can probably save yourself a lot of hassle and unreadable code in the long run by writing distinct partial specializations of Field for the 2D and 3D case:
enum Dimension : std::size_t { _2D = 2, _3D = 3 };
template <Dimension D>
using gridPoint = std::array<int, D>;
template <typename T>
struct Field_base : std::vector<T> {
// Stuff common to both specializations goes here.
using std::vector<T>::vector;
};
template <typename, Dimension>
struct Field;
template <typename T>
struct Field<T, _2D> : Field_base<T>
{
using grid_point = gridPoint<_2D>;
using Field_base<T>::Field_base;
T differentiate(const grid_point&, int) const
{
std::cout << "2D differentiate called\n";
return {};
}
};
template <typename T>
struct Field<T, _3D> : Field_base<T>
{
using grid_point = gridPoint<_3D>;
using Field_base<T>::Field_base;
T differentiate(const grid_point&, int) const
{
std::cout << "3D differentiate called\n";
return {};
}
};
For SFINAE to work, I believe the function needs to be templated so that this becomes a choice of which function compiles during overload resolution, not which function compiles during class instantiation.
I modified this as follows and it "works" on this end:
#include <iostream>
#include <vector>
enum Dimension : std::size_t { _2D = 2, _3D = 3 };
template <Dimension D>
struct gridPoint
{
int d[D];
};
template <typename T, Dimension D>
struct Field : public std::vector<T>
{
template <Dimension D2>
typename std::enable_if<D== D2 && D==_2D, T>::type
differentiate(const gridPoint<D2>& pt, int extent) const
{
std::cout << "2D differentiate called" << std::endl;
return T(0.0);
}
template <Dimension D2>
typename std::enable_if<D==D2 && D==_3D, T>::type
differentiate(const gridPoint<D2>& pt, int extent) const
{
std::cout << "3D differentiate called" << std::endl;
return T(0.0);
}
};
int main() {
Field<double, _2D> foo;
gridPoint<_2D> point { 3, 4 };
foo.differentiate(point, 3);
gridPoint<_3D> p3 { 3, 4, 5 };
Field<double, _3D> bar;
bar.differentiate(p3, 8);
return 0;
}
I didn't sort out the template foo to get this to compile with the definition out-of-line.
The compiler error provoked by your attempted out-of-line SFINAE definitions
for T Field<T,Dimension>::differentiate(const gridPoint<D>&, int) const would be:
error: prototype for ‘typename std::enable_if<(D == _2D), T>::type Field<T, D>::differentiate(const gridPoint<D>&, int) const’ does not match any in class ‘Field<T, D>’
error: candidate is: T Field<T, D>::differentiate(const gridPoint<D>&, int) const
error: prototype for ‘typename std::enable_if<(D == _3D), T>::type Field<T, D>::differentiate(const gridPoint<D>&, int) const’ does not match any in class ‘Field<T, D>’
error: candidate is: T Field<T, D>::differentiate(const gridPoint<D>&, int) const
or words to that effect.
The compiler insists that any purported out-of-line definition of a member function
of Field<T,Dimension> has the same prototype as the declaration of
of some member function, and its diagnostics spell out that this requirement is
not satisfied for either of the purported out-of-line definitions.
It is no good protesting that if the compiler would just carry on and do the SFINAE,
it then would discover that the one surviving out-of-line definition matches a member function declaration. It can't do
the SFINAE until it attempts some instantiation of Field<D,Dimension>, and making sure that
any out-of-line template/class member definitions pair off with template/class member declarations comes earlier on its
to-do list than instantiating templates. Instantiation might never happen, but orphan
member definitions are always wrong.
So, both of those SFINAE-embellished prototypes would have to appear as member
function declarations.
But then, if the compiler is to tolerate both of these SFINAE-embellished member
function declarations, they must be template member functions (not merely
member functions of a class template) and their respective std::enable_if conditions
must depend upon a template parameter of the member function. Such are the SFINAE
rules.
Summing up, what you need to write to accomplish your out-of-line SFINAE definitions is
illustrated by the following program:
#include <iostream>
#include <vector>
enum Dimension : std::size_t { _2D = 2, _3D = 3 };
template<Dimension D>
struct gridPoint {}; // ...whatever
template <typename T, Dimension D>
class Field : public std::vector<T>
{
public:
template <Dimension Dim = D>
typename std::enable_if<Dim ==_2D, T>::type
differentiate(const gridPoint<Dim>&, int) const;
template <Dimension Dim = D>
typename std::enable_if<Dim ==_3D, T>::type
differentiate(const gridPoint<Dim>&, int) const;
};
template <typename T, Dimension D> template<Dimension Dim>
typename std::enable_if<Dim ==_2D, T>::type
Field<T,D>::differentiate(const gridPoint<Dim>& pt, int extent) const
{
std::cout << "_2D differentiate" << std::endl;
return T(); // ...whatever
}
template <typename T, Dimension D> template<Dimension Dim>
typename std::enable_if<Dim ==_3D, T>::type
Field<T,D>::differentiate(const gridPoint<Dim>& pt, int extent) const
{
std::cout << "_3D differentiate" << std::endl;
return T(); // ...whatever
}
int main()
{
Field<int,_2D> f_2d;
gridPoint<_2D> gp_2d;
f_2d.differentiate(gp_2d,2);
Field<float,_3D> f_3d;
gridPoint<_3D> gp_3d;
f_3d.differentiate(gp_3d,3);
f_3d.differentiate(gp_2d,2);
return 0;
}
In this not very pleasant light, you might possibly want to review the question of whether Dimension needs to be a template parameter of
Field, or whether it might just be a template parameter of member functions of Field. As I
don't know the complete implementation of the template, I can't say. Alternatively, you might reconsider your dislike of the
template base class + partial specialization approach suggested by #casey.
Presumably you would like the alternative definitions of differentiate out-of-line because they are big and you don't want them
sprawling in the body of the class template. In thorny cases like this a plodding but fairly failsafe way of extruding template/class member definitions to be out-of-line
is first to code the template/class with inline definitions and get a successful build; then copy-paste the inline definitions to their
out-of-line places, add the required template/class qualifications and delete default specifiers; then truncate the original in-line definitions to declarations;
then get a successful build again.
The output of that example program is:
_2D differentiate
_3D differentiate
_2D differentiate
The last line is emitted by the execution f_3d.differentiate(gp_2d,2), which draws attention to the fact that the selected implementation of differentiate
is determined by the Dimension of the gridPoint<Dimension>& argument that is passed to it and not by the Dimension of the
Field<T,Dimension> on which it is invoked. Thus we can call Field<T,_3D>::differentiate<_2D>. Since you said:
This differentiate methode is computed differently depending of the Dimension D
this on the face of it seems to be the behaviour you want, as the gridPoint<Dimension>
argument differentiates the implementations of differentiate according to the value of
Dimension. But this observation revives the question: Is there really a good reason for
Dimension to be a template parameter of Field, and not just a template parameter of differentiate?
If there is really a good reason, then you want it to be impossible to call Field<T,_3D>::differentiate<_2D>
or Field<T,_2D>::differentiate<_3D>. You can achieve that by replacing all occurrences of <Dim> with
<D> in the program, though the SFINAE implementation then looks even more laboured.

Specializing single method in a big template class

In C++ if you want to partially specialize a single method in a template class you have to specialize the whole class (as stated for example in Template specialization of a single method from templated class with multiple template parameters)
This however becomes tiresome in bigger template classes with multiple template parameters, when each of them influences a single function. With N parameters you need to specialize the class 2^N times!
However, with the C++11 I think there might a more elegant solution, but I am not sure how to approach it. Perhaps somehow with enable_if? Any ideas?
In addition to the inheritance-based solution proposed by Torsten, you could use std::enable_if and default function template parameters to enable/disable certain specializations of the function.
For example:
template<typename T>
struct comparer
{
template<typename U = T ,
typename std::enable_if<std::is_floating_point<U>::value>::type* = nullptr>
bool operator()( U lhs , U rhs )
{
return /* floating-point precision aware comparison */;
}
template<typename U = T ,
typename std::enable_if<!std::is_floating_point<U>::value>::type* = nullptr>
bool operator()( U lhs , U rhs )
{
return lhs == rhs;
}
};
We take advantage of SFINAE to disable/enable the different "specializations" of the function depending on the template parameter. Because SFINAE can only depend on function parameters, not class parameters, we need an optional template parameter for the function, which takes the parameter of the class.
I prefer this solution over the inheritance based because:
It requires less typing. Less typing probably leads to less errors.
All specializations are written inside the class. This way to write the specializations holds all of the specializations inside the original class , and make the specializations look like function overloads, instead of tricky template based code.
But with compilers which have not implemented optional function template parameters (Like MSVC in VS2012) this solution does not work, and you should use the inheritance-based solution.
EDIT: You could ride over the non-implemented-default-function-template-parameters wrapping the template function with other function which delegates the work:
template<typename T>
struct foo
{
private:
template<typename U>
void f()
{
...
}
public:
void g()
{
f<T>();
}
};
Of course the compiler can easily inline g() throwing away the wrapping call, so there is no performance hit on this alternative.
One solution would be to forward from the function, you want to overload to some implementation that depends on the classes template arguments:
template < typename T >
struct foo {
void f();
};
template < typename T >
struct f_impl {
static void impl()
{
// default implementation
}
};
template <>
struct f_impl<int> {
static void impl()
{
// special int implementation
}
};
template < typename T >
void foo< T >::f()
{
f_impl< T >::impl();
}
Or just use private functions, call them with the template parameter and overload them.
template < typename T >
class foo {
public:
void f()
{
impl(T());
}
private:
template < typename G >
void impl( const G& );
void impl( int );
};
Or if it's really just one special situation with a very special type, just query for that type in the implementation.
With enable_if:
#include <iostream>
#include <type_traits>
template <typename T>
class A {
private:
template <typename U>
static typename std::enable_if<std::is_same<U, char>::value, char>::type
g() {
std::cout << "char\n";
return char();
}
template <typename U>
static typename std::enable_if<std::is_same<U, int>::value, int>::type
g() {
std::cout << "int\n";
return int();
}
public:
static T f() { return g<T>(); }
};
int main(void)
{
A<char>::f();
A<int>::f();
// error: no matching function for call to ‘A<double>::g()’
// A<double>::f();
return 0;
}
Tag dispatching is often the clean way to do this.
In your base method, use a traits class to determine what sub version of the method you want to call. This generates a type (called a tag) that describes the result of the decision.
Then perfect forward to that implememtation sub version passing an instance of the tag type. Overload resolution kicks in, and only the implememtation you want gets instantiated and called.
Overload resolution based on a parameter type is a much less insane way of handling the dispatch, as enable_if is fragile, complex at point of use, gets really complex if you have 3+ overloads, and there are strange corner cases that can surprise you with wonderful compilation errors.
Maybe i'm wrong but chosen best anwser provided by Manu343726 has an error and won't compile. Both operator overloads have the same signature. Consider best anwser in question std::enable_if : parameter vs template parameter
P.S. i would put a comment, but not enough reputation, sorry

Prevent templated member function from being instantiated for a given type

I have a templated matrix class that I explicitly instantiate for various POD types and custom class types. Some of the member functions however don't make sense for a few of such custom types. For example:
Matrix<int> LoadFile(....); // This makes sense
Matrix<My_custom_class> LoadFile(...); //This doesn't make sense in the context of the custom class
Can I prevent the instantiation of the LoadFile function (which is a member function) for Matrix objects of select types? So far I have avoided the issue by making LoadFile a friend function and then explicitly controlling its instantiation. But I want to know if I can do this when LoadFile is a member function of Matrix.
The first question is whether you really need to control this. What happens if they call that member function on a matrix that stores My_custom_class? Can you provide support in your class (or the template) so that the member function will work?
If you really want to inhibit the use of those member functions for some particular type, then you can use specialization to block the particular instantiation:
template <typename T>
struct test {
void foo() {}
};
template <>
inline void test<int>::foo() = delete;
Or even just add static_asserts to the common implementation verifying the preconditions for what types is it allowed or disallowed?
template <typename T>
struct test {
void foo() {
static_assert(std::is_same<T,int>::value || std::is_same<T,double>::value,
"Only allowed for int and double");
// regular code
}
};
with std::enable_if, this is the best I can come up with
template< typename T >
struct Matrix {
template< typename T >
Matrix< typename std::enable_if<std::is_integral<T>::value, T>::type >
LoadFile()
{
return Matrix<T>();
}
};
Matrix<int> a;
Matrix<int> b = a.LoadFile<int>()
only type int compile while other don't.
Can I prevent the instantiation of the LoadFile function (which is a member function) for Matrix objects of select types?
Your best bet here would be to use a static_assert that would create a compiler error when you attempt to call the method in a version of the class instantiated with a blocked type. Using std::enable_if, and other methods that would selectively "disable" a method itself would require you to create partial or full specializations of the class with and without the methods in question in order to prevent compiler errors. For instance, AFAIK, you cannot do the following:
template <typename T>
struct test
{
static const bool value = false;
};
template<>
struct test<double>
{
static const bool value = true;
};
template<typename T>
struct example
{
void print() { cout << "Printing value from print()" << endl; }
typename enable_if<test<T>::value, T>::type another_print()
{
cout << "Printing value from another_print()" << endl;
return T();
}
};
If you attempted to instantiate an example<int>, etc., you would end up with a compiler error at the point of instantiation of the object type. You couldn't simply call example<int>::print() and be okay, and only run into a problem if you chose to call example<int>::another_print(). Specializations of example<T> could get you around the issue, but that can be a bit of a mess. As originally surmised, a static_assert would probably be the easiest case to handle, along with a nice message to the end-user explaining what went wrong.
Keep in mind that creating compiler errors is the goal, and it's a good one to have. If you blocked a method from being instantiated, and the end-user decided to invoke it, you'd end up with a compiler error either way. The version without the static_assert will leave a lot of head-scratching as the user of your class attempts to parse a probably very verbose compiler error message, where-as the static_assert method is direct and to the point.
If the selected set of types is known at compile time, and you are using c++11 with a compiler that supports type aliases, uniform initialization and constexpr (for example gcc 4.7) you can make your code a bit cleaner like this (from previous example above by yngum):
template <bool Cond, class T = void>
using enable_if_t = typename std::enable_if<Cond, T>::type;
template< typename T >
struct Matrix {
template< typename T >
//std::is_integral has constexpr operator value_type() in c++11. This will work thanks to uniform init + constexpr. With the alias, no more need for typename + ::type
Matrix<enable_if_t<std::is_integral<T>{}>>
LoadFile()
{
return Matrix<T>();
}
};
Matrix<int> a;
Matrix<int> b = a.LoadFile<int>();
Beware of compatibility of this code, though, because these features have been only recently supported and some compilers don't do yet. You can see more about c++11 compiler support here.
If you could use the TypeLists from the ( http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315 ) - Loki you could implement something like:
template<bool>
struct Static_Assert;
template<>
struct Static_Assert<true>{};
class B{};
template<typename T>
class A{
public:
A(){
Static_Assert< 0 == utils::HasType<T, TYPELIST_2(B,int) >::value >();
}
};
Then your HasType would be something like:
template<typename T, typename TList>
struct HasType{
enum { value = 0+HasType< T, typename TList::Tail >::value };
};
template<typename T>
struct HasType< T, NullType >{
enum { value = 0 };
};
template<typename T, typename U>
struct HasType< T, TypeList<T, U> >{
enum { value = 1 };
};
In the list you can add the classes which you would like prevent to be passed as the template parameters.