1

If I have a template function like

template<typename T>
void doSomething(const T arg) {.....}

then I do not know ahead of time if T is a simple int or if it is a huge struct. If it is an int, passing by value makes sense, while the struct should be passed by reference.

How do I design a template function which works sensibly with both types of argument?

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
JoeTaicoon
  • 1,383
  • 1
  • 12
  • 28
  • Won't your function be necessarily `inline` (since it is header only)? In this case, the compiler may optimise `const int&` arguments to `int`. You can (=should) test whether there is any measurable benefit from using plain values instead of `const` references. – Walter Aug 12 '16 at 07:52
  • Possible duplicate of [Generic for loop for elementary and complex type](http://stackoverflow.com/questions/37272094/generic-for-loop-for-elementary-and-complex-type) – Humam Helfawi Aug 12 '16 at 07:54

2 Answers2

3

The boost::call_traits library has several helpers for stuff like this. In particular, call_traits<T>::param_type

Defines a type that represents the "best" way to pass a parameter of type T to a function.

You use it like so:

template<typename T>
void doSomething(typename boost::call_traits<T>::param_type arg) {.....}

It basically works by specializing the class for speacial cases. So, e.g., your int case from the question is (indirectly) specialized to int (and not int &).

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
  • 3
    This is obviously useful for something like boost, but for most templates that people write in day-to-day work, I would say "don't sweat it". The optimizer will probably deal with the different between `const int& arg` and `int arg` - given that templates are pretty much always inline. – Martin Bonner supports Monica Aug 12 '16 at 07:49
  • @MartinBonner That makes sense. Also, "root of all evil" and that. Still, the question was asked. – Ami Tavory Aug 12 '16 at 07:50
  • @MartinBonner: How do you come to the assumption (or maybe fact) proposed by "given that templates are pretty much always inline"? Is that something to rely on? – thokra Aug 12 '16 at 07:58
  • 2
    @thokra: Yes, you can rely on that. In general you have to define template functions and member functions in header files (not in separately compiled .cpp files). The only exception is when you know all the types that you are going to instantiate the templates for (at which point the problem goes away). – Martin Bonner supports Monica Aug 12 '16 at 08:11
  • See http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – Martin Bonner supports Monica Aug 12 '16 at 08:11
1

Your question is a XY problem. You're asking for a solution to a problem that only arises from a poor 'solution' to another problem. So, here I decide to answer your initial problem instead.

Since your template function will almost certainly have to be inline, most compilers will optimize the function call away and with it your problem. Thus, it may actually not matter what you use, but T const&arg is the more conservative.

So, before 'solving' this problem, you should test whether there is any measurable difference between the two options for a simple int (with production-style optimisation switched on).

Community
  • 1
  • 1
Walter
  • 44,150
  • 20
  • 113
  • 196