Template parameters in C++ - c++

Suppose I have arbitrary template method, which could receive parameters by value and by const reference (obviously, for trivial types and for objects accordingly).
How is this situation handled when writing template function prototypes?
I could make something like:
template <typename T> void Foo(T value) {
// Do something.
}
template <typename T> void Foo(const T& value) {
// Do something, yeah.
}
// Specialization for first prototype.
template <> void Foo<int>(int value) { }
// Specialization for second prototype.
template <> void Foo<Object>(const Object& value) { }
But this approach is only okay for trivial functions, that act purely as a wrapper for some other calls.
If the function (non-templated version) has a lot of code inside it, this means I would have to copy the code twice.
Can I make something smarter here?

Just take by const reference ALWAYS, because there isn't much overhead in passing primitive types as const references.

Write your template code for const references only and rely on the compiler to optimize the references away.

Related

Detect template parameter type [duplicate]

In my template-ized function, I'm trying to check the type T is of a specific type. How would I do that?
p/s I knew the template specification way but I don't want to do that.
template<class T> int foo(T a) {
// check if T of type, say, String?
}
Thanks!
Instead of checking for the type use specializations. Otherwise, don't use templates.
template<class T> int foo(T a) {
// generic implementation
}
template<> int foo(SpecialType a) {
// will be selected by compiler
}
SpecialType x;
OtherType y;
foo(x); // calls second, specialized version
foo(y); // calls generic version
If you don't care about compile-time, you may use boost::is_same.
bool isString = boost::is_same<T, std::string>::value;
As of C++11, this is now part of the standard library
bool isString = std::is_same<T, std::string>::value
hmm because I had a large portion of
same code until the 'specification'
part.
You can use overloading, but if a large part of the code would work for any type, you might consider extracting the differing part into a separate function and overload that.
template <class T>
void specific(const T&);
void specific(const std::string&);
template <class T>
void something(const T& t)
{
//code that works on all types
specific(t);
//more code that works on all types
}
I suppose you could use the std::type_info returned by the typeid operator
I suspect someone should tell you why it might not be a good idea to avoid using overloading or specialization. Consider:
template<class T> int foo(T a) {
if(isAString<T>()) {
return a.length();
} else {
return a;
}
}
You might think on a first sight that it will work for int too, because it will only try to call length for strings. But that intuition is wrong: The compiler still checks the string branch, even if that branch is not taken at runtime. And it will find you are trying to call a member function on non-classes if T is an int.
That's why you should separate the code if you need different behavior. But better use overloading instead of specialization, since it's easier to get a clue how things work with it.
template<class T> int foo(T a) {
return a;
}
int foo(std::string const& a) {
return a.length();
}
You have also better separated the code for different paths of behavior. It's not all anymore clued together. Notice that with overloading, the parameters may have different type forms and the compiler will still use the correct version if both match equally well, as is the case here: One can be a reference, while the other can not.
You can check using type_traits (available in Boost and TR1) (e.g. is_same or is_convertible) if you really want to avoid specialization.
You can perform static checks on the type that you have received (look at the boost type traits library), but unless you use specialization (or overloads, as #litb correctly points out) at one point or another, you will not be able to provide different specific implementations depending on the argument type.
Unless you have a particular reason (which you could add to the question) not to use the specialization in the interface just do specialize.
template <> int subtract( std::string const & str );
If you are using C++11 or later, std::is_same does exactly what you want:
template <typename T>
constexpr bool IsFloat() { return std::is_same<T, float>::value; }
template <typename T>
void SomeMethodName() {
if (IsFloat<T>()) {
...
}
}
http://en.cppreference.com/w/cpp/types/is_same

How can I get the C++ compiler to deduce T indirectly?

My template-fu is rather weak. I have this code:
template<typename T>
void Foo(void(*func)(T*)) { }
void Callback(int* data) { }
int Test()
{
Foo(Callback);
}
...but I'd like something more readable than C's nasty function pointer syntax of void(*func)(T*).
Someone on my team suggested this:
template<typename T>
struct Types
{
typedef void Func(T*);
};
template<typename T>
void Foo2(typename Types<T>::Func* func) {}
void Test2()
{
Foo2(Callback); // could not deduce template argument for 'T'
Foo2<int>(Callback); // ok
}
(I'm still debating whether this is actually more readable, but that's a separate issue.)
How can I help the compiler figure out what T is without needing to explicitly specify it in the caller?
You can extract T from the function type using a traits class.
template<class F>
struct CallbackTraits;
template<class T>
struct CallbackTraits<void(*)(T)>
{
typedef T ArgumentType;
};
Your example can be modified like this:
template<typename F>
void Foo(F func)
{
typedef typename CallbackTraits<F>::ArgumentType T;
}
void Callback(int* data) { }
int Test()
{
Foo(Callback);
}
This technique is used in the boost type-traits library:
http://www.boost.org/doc/libs/1_57_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html
This blog post goes into a bit more detail about the implementation of the technique:
https://functionalcpp.wordpress.com/2013/08/05/function-traits/
Unfortunately this approach hides the information in the signature of Foo about the constraints on the argument passed in. In the above example the argument must be a function of type void(T*).
This alternative syntax does the same as the original example while being slightly more readable:
template<typename T>
void Foo(void func(T*)) { }
Another alternative syntax that may be more readable can be achieved using c++11's alias templates as follows:
template<typename T>
using Identity = T;
template<typename T>
void Foo(Identity<void(T*)> func) { }
Unforunately the latest MSVC fails to compile this, reporting an internal compiler error.
You won't be able to deduce the type based on a nested name: there is no reason why different instantiations of the outer type won't define an identical inner type. You could use a using alias, though:
template <typename T>
using Function = auto (*)(T*) -> void;
template <typename T>
void Foo(Function<T>) {
}
Personally, I would recommend against using any of that, however: in practice it seems much more advisable to actually take a function object which later allows using object with suitable function call operators to be used. For callbacks it is quite common that you'll need to pass in some auxiliary data. That is, you would either use an unconstrained template or one which takes a type-erased type, depending on what you want to do exactly:
template <typename Fun>
void Unconstrained(Fun fun) {
}
template <typename T>
void TypeErased(std::function<void(T*)> fun) {
}
The unconstrained version has the advantage that it can potentially inline the function call but it has the disadvantage that every function object type creates a new instantiation and that the argument types are likely to vary. The type-erased version effectively has to do something like a virtual function call but there is just one instantiation of the function template (per argument type T, of course).
Admittedly, the type-erased version's type won't be deduced from a function pointer (or any other argument which isn't a std::function<void(X*)>), i.e., you may want to have a forwarding function
template <typename T>
void TypeErased(Function<T> fun) {
TypeErased(std::function<void(T)>(fun));
}
In C++98 and C++03 template argument deduction only works with functions (and methods).
I don't think the picture changed in the more recent standards.

local variable as non-type template argument

I want to do something like the following:
Example(&Class::MemberFunction, this));
//...
template<class T_CLASS>
inline static void Example(void (T_CLASS::*MemberFunctionPointer)(), T_CLASS* InstancePointer)
{
SomeClass<T_CLASS>::Bind<MemberFunctionPointer>(InstancePointer);
}
But I get the error: *template parameter 'T_MEMBER_FUNCTION' : 'MemberFunctionPointer' : a local variable cannot be used as a non-type argument*
Any solutions for this problem? I want to provide an easier way to call "Bind"
Thanks, Mirco
//edit:
I want MemberFunctionPointer to be a non-type template parameter because in "Bind" I again need it as a template argument.
As you wrote in your answers, in my case MemberFunctionPointer is a variable and its value is unknown at compile time. But MemberFunctionPointer always points to the same function. Is there a way to for example make it constant so that the compiler knows it at compile time?
There are two kinds of things template parameters can be: types and compile-time constant expressions. The contents of a function parameter is not a compile-time determinable value. And therefore, the compiler cannot instantiate a template based on it.
Remember: a template is a type. And types must be determinable at compile time.
You probably should pass the member pointer as an argument to the Bind function.
I am not quite sure what you are trying to achieve?
If a MemberFunctionPointer is a variable, that the value of is unknown at compile time and, for example, may depend on some user behaviour - then it cannot be used as a template argument.
If, on the other hand, MemberFunctionPointer can be actually deduced at compile-time, you should pass it as a template argument, instead of a function parameter. Consider the following example:
(use Bind and call in the first case; in the second case, use StaticBind and callStatic)
#include <stdio.h>
class X {
public:
int x;
void foo() {printf("foo\n");}
void bar() {printf("bar\n");}
};
template <typename T>
class SomeClass {
public:
static void Bind(void (T::*MemberFunctionPointer)(), T *obj) {
(obj->*MemberFunctionPointer)();
}
template <void (T::*MemberFunctionPointer)()>
static void StaticBind(T *obj) {
(obj->*MemberFunctionPointer)();
}
};
template <class C>
static inline void call(void (C::*MemberFunctionPointer)(), C *obj) {
SomeClass<C>::Bind(MemberFunctionPointer,obj);
}
template <class C, void (C::*MemberFunctionPointer)()>
static inline void callStatic(C *obj) {
SomeClass<C>::template StaticBind<MemberFunctionPointer>(obj);
}
int main() {
X obj;
call<X>(&X::foo,&obj);
callStatic<X,&X::bar>(&obj);
return 0;
}
Template parameters have to be known at compile-time. The contents of a pointer variable that is a function's parameter depends on how this function is invoked. This is not known at compile-time!
If you know this pointer at compile-time already, you can turn the function pointer runtime parameter into a template parameter:
template<class T_CLASS, void(T_CLASS::*MemFunPtr)()>
void Example(T_CLASS* InstancePointer) {...}
Here, MemFunPtr is a template parameter that is known at compile-time and can thus be resused as a template parameter for another function or class template...
MemberFunctionPointer is a variable not a type (or compile-time constant), hence cannot be used, what you need is the real signature of that function, something like this may be better..
template<typename T_FUNC_PTR, class T_CLASS>
inline static void Example(T_FUNC_PTR fPtr, T_CLASS* InstancePointer)
{
SomeClass<T_CLASS>::Bind<T_FUNC_PTR>(fPtr, InstancePointer);
}
i.e. let the compiler deduce the type of the function pointer (NOTE: you will have to propagate the pointer to the function too), to call
Example(&foo::bar, foo_inst);
This is untested and off the top of my head, so the syntax could be slightly off...
EDIT: here is a simpler example to demonstrate the concept:
#include <iostream>
struct foo
{
void bar() { std::cout << "foo::bar()" << std::endl; }
};
template<typename T_FUNC_PTR, typename T_CLASS>
void exec(T_FUNC_PTR ptr, T_CLASS& inst)
{
(inst.*ptr)();
}
int main(void)
{
foo inst;
exec(&foo::bar, inst);
}

How do I check my template class is of a specific classtype?

In my template-ized function, I'm trying to check the type T is of a specific type. How would I do that?
p/s I knew the template specification way but I don't want to do that.
template<class T> int foo(T a) {
// check if T of type, say, String?
}
Thanks!
Instead of checking for the type use specializations. Otherwise, don't use templates.
template<class T> int foo(T a) {
// generic implementation
}
template<> int foo(SpecialType a) {
// will be selected by compiler
}
SpecialType x;
OtherType y;
foo(x); // calls second, specialized version
foo(y); // calls generic version
If you don't care about compile-time, you may use boost::is_same.
bool isString = boost::is_same<T, std::string>::value;
As of C++11, this is now part of the standard library
bool isString = std::is_same<T, std::string>::value
hmm because I had a large portion of
same code until the 'specification'
part.
You can use overloading, but if a large part of the code would work for any type, you might consider extracting the differing part into a separate function and overload that.
template <class T>
void specific(const T&);
void specific(const std::string&);
template <class T>
void something(const T& t)
{
//code that works on all types
specific(t);
//more code that works on all types
}
I suppose you could use the std::type_info returned by the typeid operator
I suspect someone should tell you why it might not be a good idea to avoid using overloading or specialization. Consider:
template<class T> int foo(T a) {
if(isAString<T>()) {
return a.length();
} else {
return a;
}
}
You might think on a first sight that it will work for int too, because it will only try to call length for strings. But that intuition is wrong: The compiler still checks the string branch, even if that branch is not taken at runtime. And it will find you are trying to call a member function on non-classes if T is an int.
That's why you should separate the code if you need different behavior. But better use overloading instead of specialization, since it's easier to get a clue how things work with it.
template<class T> int foo(T a) {
return a;
}
int foo(std::string const& a) {
return a.length();
}
You have also better separated the code for different paths of behavior. It's not all anymore clued together. Notice that with overloading, the parameters may have different type forms and the compiler will still use the correct version if both match equally well, as is the case here: One can be a reference, while the other can not.
You can check using type_traits (available in Boost and TR1) (e.g. is_same or is_convertible) if you really want to avoid specialization.
You can perform static checks on the type that you have received (look at the boost type traits library), but unless you use specialization (or overloads, as #litb correctly points out) at one point or another, you will not be able to provide different specific implementations depending on the argument type.
Unless you have a particular reason (which you could add to the question) not to use the specialization in the interface just do specialize.
template <> int subtract( std::string const & str );
If you are using C++11 or later, std::is_same does exactly what you want:
template <typename T>
constexpr bool IsFloat() { return std::is_same<T, float>::value; }
template <typename T>
void SomeMethodName() {
if (IsFloat<T>()) {
...
}
}
http://en.cppreference.com/w/cpp/types/is_same

How to call a templated function if it exists, and something else otherwise?

I want to do something like
template <typename T>
void foo(const T& t) {
IF bar(t) would compile
bar(t);
ELSE
baz(t);
}
I thought that something using enable_if would do the job here, splitting up foo into two pieces, but I can't seem to work out the details. What's the simplest way of achieving this?
There are two lookups that are done for the name bar. One is the unqualified lookup at the definition context of foo. The other is argument dependent lookup at each instantiation context (but the result of the lookup at each instantiation context is not allowed to change behavior between two different instantiation contexts).
To get the desired behavior, you could go and define a fallback function in a fallback namespace that returns some unique type
namespace fallback {
// sizeof > 1
struct flag { char c[2]; };
flag bar(...);
}
The bar function will be called if nothing else matches because the ellipsis has worst conversion cost. Now, include that candidates into your function by a using directive of fallback, so that fallback::bar is included as candidate into the call to bar.
Now, to see whether a call to bar resolves to your function, you will call it, and check whether the return type is flag. The return type of an otherwise chosen function could be void, so you have to do some comma operator tricks to get around that.
namespace fallback {
int operator,(flag, flag);
// map everything else to void
template<typename T>
void operator,(flag, T const&);
// sizeof 1
char operator,(int, flag);
}
If our function was selected then the comma operator invocation will return a reference to int. If not or if the selected function returned void, then the invocation returns void in turn. Then the next invocation with flag as second argument will return a type that has sizeof 1 if our fallback was selected, and a sizeof greater 1 (the built-in comma operator will be used because void is in the mix) if something else was selected.
We compare the sizeof and delegate to a struct.
template<bool>
struct foo_impl;
/* bar available */
template<>
struct foo_impl<true> {
template<typename T>
static void foo(T const &t) {
bar(t);
}
};
/* bar not available */
template<>
struct foo_impl<false> {
template<typename T>
static void foo(T const&) {
std::cout << "not available, calling baz...";
}
};
template <typename T>
void foo(const T& t) {
using namespace fallback;
foo_impl<sizeof (fallback::flag(), bar(t), fallback::flag()) != 1>
::foo(t);
}
This solution is ambiguous if the existing function has an ellipsis too. But that seems to be rather unlikely. Test using the fallback:
struct C { };
int main() {
// => "not available, calling baz..."
foo(C());
}
And if a candidate is found using argument dependent lookup
struct C { };
void bar(C) {
std::cout << "called!";
}
int main() {
// => "called!"
foo(C());
}
To test unqualified lookup at definition context, let's define the following function above foo_impl and foo (put the foo_impl template above foo, so they have both the same definition context)
void bar(double d) {
std::cout << "bar(double) called!";
}
// ... foo template ...
int main() {
// => "bar(double) called!"
foo(12);
}
litb has given you a very good answer. However, I wonder whether, given more context, we couldn't come up with something that's less generic, but also less, um, elaborate?
For example, what types can be T? Anything? A few types? A very restricted set which you have control over? Some classes you design in conjunction with the function foo? Given the latter, you could simple put something like
typedef boolean<true> has_bar_func;
into the types and then switch to different foo overloads based on that:
template <typename T>
void foo_impl(const T& t, boolean<true> /*has_bar_func*/);
template <typename T>
void foo_impl(const T& t, boolean<false> /*has_bar_func*/);
template <typename T>
void foo(const T& t) {
foo_impl( t, typename T::has_bar_func() );
}
Also, can the bar/baz function have just about any signature, is there a somewhat restricted set, or is there just one valid signature? If the latter, litb's (excellent) fallback idea, in conjunction with a meta-function employing sizeof might be a bit simpler. But this I haven't explored, so it's just a thought.
I think litb's solution works, but is overly complex. The reason is that he's introducing a function fallback::bar(...) which acts as a "function of last resort", and then goes to great lengths NOT to call it. Why? It seems we have a perfect behavior for it:
namespace fallback {
template<typename T>
inline void bar(T const& t, ...)
{
baz(t);
}
}
template<typename T>
void foo(T const& t)
{
using namespace fallback;
bar(t);
}
But as I indicated in a comment to litb's original post, there are many reasons why bar(t) could fail to compile, and I'm not certain this solution handles the same cases. It certainly will fail on a private bar::bar(T t)
If you're willing to limit yourself to Visual C++, you can use the __if_exists and __if_not_exists statements.
Handy in a pinch, but platform specific.
EDIT: I spoke too soon! litb's answer shows how this can actually be done (at the possible cost of your sanity... :-P)
Unfortunately I think the general case of checking "would this compile" is out of reach of function template argument deduction + SFINAE, which is the usual trick for this stuff. I think the best you can do is to create a "backup" function template:
template <typename T>
void bar(T t) { // "Backup" bar() template
baz(t);
}
And then change foo() to simply:
template <typename T>
void foo(const T& t) {
bar(t);
}
This will work for most cases. Because the bar() template's parameter type is T, it will be deemed "less specialised" when compared with any other function or function template named bar() and will therefore cede priority to that pre-existing function or function template during overload resolution. Except that:
If the pre-existing bar() is itself a function template taking a template parameter of type T, an ambiguity will arise because neither template is more specialised than the other, and the compiler will complain.
Implicit conversions also won't work, and will lead to hard-to-diagnose problems: Suppose there is a pre-existing bar(long) but foo(123) is called. In this case, the compiler will quietly choose to instantiate the "backup" bar() template with T = int instead of performing the int->long promotion, even though the latter would have compiled and worked fine!
In short: there's no easy, complete solution, and I'm pretty sure there's not even a tricky-as-hell, complete solution. :(
//default
//////////////////////////////////////////
template <class T>
void foo(const T& t){
baz(t);
}
//specializations
//////////////////////////////////////////
template <>
void foo(const specialization_1& t){
bar(t);
}
....
template <>
void foo(const specialization_n& t){
bar(t);
}
Are you not able to use full specialisation here (or overloading) on foo. By say having the function template call bar but for certain types fully specialise it to call baz?