3

Suppose, we declare the template:

template <class functor, int index>
class MyClass
{
public:
    MyClass(){someFunction(index);}
private:
    void someFunction(int index)
    {
        while(index--)
            functor();
    }
    int commonFunction(void)
    {
        return M_PI;
    }
};

Pay attention that the method commonFunction doesn`t depend on the template parameters.

Client uses this template:

MyClass<func1,100> t1;
MyClass<func2,100> t2;
// ...
MyClass<funci,100> ti;
// where i, for example in 1 .. 1000

Will instantiation of the template lead to the duplication of commonFunction in the binary code?
Can a compiler prevent that duplication?
Does C++ standart defines that duplication can be prevented, so every compiler should provide optimization?

Of course this can be easily solved by implementing common functionality for all templates in a base class and moving differences in the templated class, like this:

class baseMyClass
{
    int commonFunction(void)
    {
        return M_PI;
    }
};

template <class functor, int index>
class MyClass : private baseMyClass
{
public:
    MyClass(){someFunction(index);}
private:
    void someFunction(int index)
    {
        while(index--)
            functor();
    }
};

But the purpose of my question is to find out:
Does standart defines that in the cases that look like the one I gave optimization should be performed, so we can simply use template and rely on a compiler?

spin_eight
  • 3,925
  • 10
  • 39
  • 61

2 Answers2

4

Does standart defines that in the cases that look like the one I gave optimization should be performed, so we can simply use template and rely on a compiler?

No, the Standard does not require by any means that conforming compilers perform such kind of optimization. Code bloating is known to be one of the drawbacks of templates.

This said, since your function does not do anything else than returning a constant, it will probably be inlined, and even in case it will not be inlined, it is possible that the linker will recognize that several identical instantiations of that function have been generated, and merge them all.

However, this behavior is not mandated by the Standard.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • If it is known problem, why not to add to the standart requirements for the compilers in order to sort it out? – spin_eight May 25 '13 at 11:00
  • also, do compilers provide optimization? Is it a good practice to choose compiler what provides optimization and use only it, what drawback can be? – spin_eight May 25 '13 at 11:02
  • "even in case it will not be inlined, it is likely that the linker will recognize that several identical instantiations of that function has been generated, and merge them all." -- Do any compilers (linkers) really do that? Is that even valid? The standard requires pointers to different functions to not compare as equal, does it not? And the linker in my experience has no knowledge of which functions' addresses can be taken. –  May 25 '13 at 11:04
  • @spin_eight: The Standard never enforces optimizations, and never prohibits them, as long as the so-called "*as-if*" rule is respected. Perhaps *in some cases* this optimization is possible, but *in the general case* it is not - it would require the compiler to figure out whether two pieces of code do the same thing or not. – Andy Prowl May 25 '13 at 11:05
  • @hvd: But what if the program contains no function pointers? Under the as-if rule, the compiler would be allowed to merge them – Andy Prowl May 25 '13 at 11:07
  • @AndyProwl You're right, it's allowed as long as the function address is never used for anything other than to call the function. I would still be surprised if any linker performs this optimisation: unless the linker can tell how a reference to a function is used, it has to take the safe route and assume it might be compared to another function. –  May 25 '13 at 11:11
  • As `commonFunction` is a member function, wouldn't we have to compare member function pointers anyway? They already differ by their type, so I think this does not prohibit the optimization. The result of a cast to a different pointer to member function is unspecified [expr.reinterpret.cast]/10 – dyp May 25 '13 at 11:16
  • @hvd: True. I am not a compiler expert, so apart from being 99% sure that such a short function would be inlined, as long as the function is not inlined I can only tell what seems formally reasonable to me (in fact, I edited the "it is likely" into "it is possible", thank you for that). Formally, I just know the "as-if" rule does not prevent merging them, and for really simple functions I can imagine that to be possible. – Andy Prowl May 25 '13 at 11:16
  • @DyP: I'm not sure I understand what you mean by "compare member function pointers anyway". Notice, that here, the function does not use the `this` pointer at all... – Andy Prowl May 25 '13 at 11:17
  • @AndyProwl `&MyClass::commonFunction == &MyClass::commonFunction` -> types differ – dyp May 25 '13 at 11:19
  • @AndyProwl I'm talking about the problem of optimization hvd wants to point out. If you want to compare pointers to two different instantiations of the `commonFunction`, you'll have to use a `reinterpret_cast` which results in an unspecified value. Therefore, IMO, the guarantee they would **not** compare equal does not hold here. – dyp May 25 '13 at 11:21
  • 1
    @Dyp: Also relevant is [this](http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=561) and, probably even more, [this](http://stackoverflow.com/questions/9323273/why-two-functions-print-the-same-address) – Andy Prowl May 25 '13 at 11:25
  • @AndyProwl Nice, thank you. But IMO it's even simpler here as we have *member* functions, which have different types. We cannot simply compare them, we have to apply a cast to one of them, e.g. `&MyClass::commonFunction == reinterpret_cast::*)()> (&MyClass::commonFunction)`. The result of this comparison is **not** specified AFAIK. – dyp May 25 '13 at 11:32
  • @DyP: Indeed, the result is unspecified – Andy Prowl May 25 '13 at 11:36
  • Visual Studio does in fact fold functions with identical assembly bodies. But it is not Standard at all. – Puppy May 25 '13 at 11:59
0

The standard does not mandate optimisation on any case. So the answer to your last question is no for any case you can think of. Now, the standard does not prevent optimisation either in this case, and I guess many compilers will be smart enough to do it in this simple case.

Gorpik
  • 10,940
  • 4
  • 36
  • 56