6

I know that the following code will result in a linking error:

//first.cpp
void test(){
    //random code
}

//second.cpp
void test(){
    //random code
}

so lets say that we have this function template:

template<typename T>
T test(){
    //random code
}

and are doing this:

//first.cpp
...
test<void>();

//second.cpp
...
test<void>();

so the way I understand how compiler works is that it only cares for each file individually so it only cares that test<void>() must have a definition therefore it will create one. same thing goes for the second.cpp then why don't we get an linker error at later stage when there are two definitions for test<void>.(I think this should be same as the first example where those two void test() functions in separate files lead to a linking error)

if this is a duplicate I'm sorry I literally didn't know how to search for this.

cigien
  • 57,834
  • 11
  • 73
  • 112
ClassY
  • 744
  • 5
  • 20
  • 2
    Template instantiations are implicitly inline. You can have the same effect with non-template functions if you add `inline` keyword, as in `inline void test() {}` - this way you won't get linker errors in your first example either. – Igor Tandetnik Jul 04 '21 at 19:36
  • There are [several relevant questions](https://stackoverflow.com/search?q=%5Bc%2B%2B%5D+template+odr), such as [this one](https://stackoverflow.com/questions/52664184/why-does-explicit-template-instantiation-not-break-odr). – 1201ProgramAlarm Jul 04 '21 at 19:45
  • I've rolled back your edit. Please don't ask follow up questions after receiving answers. Go ahead and post a new question if you want to. – cigien Jul 05 '21 at 01:25
  • 1
    Others have answered in terms of the standard, but if you're interested in what's happening at a lower level, Google "weak symbol". You might also gain some insight from my answer here: https://stackoverflow.com/a/51229603/1405588 – o11c Jul 05 '21 at 01:34
  • @o11c so if I understand correctly are all template codes _weak by default since we have established that they are NOT inline? because in [this](https://stackoverflow.com/questions/52664184/why-does-explicit-template-instantiation-not-break-odr), the explicit instantiation with the biggest size is taken therefore its not ub and its actually following the rules. – ClassY Jul 05 '21 at 06:37

2 Answers2

4

The linker doesn't complain because the standard says so:

[basic.def.odr]/13

There can be more than one definition of a
...
— inline function or variable ...

— templated entity ...

In this regard, the linker handles them as if they were inline.

Note that they're not actually inline (for the purposes of optimizations). You can mark them as inline yourself, hinting the compiler that they should be inlined.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
0

Try it with inline

//first.cpp
inline void test(){
    //random code
}

//second.cpp
inline void test(){
    //random code
}

This tells the linker not to worry about multiple definitions of that function in multiple translation units. Templates have this without adding inline.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Koronis Neilos
  • 700
  • 2
  • 6
  • 20