2

If there is valid code in c++03, Can it break in c++11 because of Internal linkage rule introduced?

Clause C.2.6 Clause 14: templates point 3 14.6.4.2

I am not able to think of any example.

Any help is appreciated.

a learner
  • 321
  • 1
  • 11
  • C++ is backward compatible so it should be valid code IMO – NutCracker Jan 14 '21 at 10:23
  • 1
    An example of template instantiations with internal linkage include templated functions (not member functions of template classes) that are deliberately instantiated in the unnamed namespace. Internal linkage of instantations of template functions never happen implicitly (i.e. they always result from deliberate actions by the programmer). If you have code which does that, then this rule can cause some of that code to work differently in C++11 compared with C++03 (a different overload of some functions will be called). Programmers, practically, rarely have reason to write such code though. – Peter Jan 14 '21 at 10:33
  • @NutCracker i get it, but i have seen "https://stackoverflow.com/questions/23047198/can-c-code-be-valid-in-both-c03-and-c11-but-do-different-things" and "https://stackoverflow.com/questions/14595992/why-stdsort-doesnt-accept-compare-classes-declared-within-a-function/14596065#14596065" saying code gives different output because of internal linkage. but its not a valid code in c++03, thats why its not a valid example. – a learner Jan 14 '21 at 10:35
  • @Peter I couldn't think of an ex. of code, because in case of overloading then definitely local (internal linkage) function would have higher scope.. then I guess there'll be an error or warning in c++03 itself. – a learner Jan 14 '21 at 10:40
  • 2
    @NutCracker, there are several minor corner cases in detail where full backward compatibility cannot be ensured with focus on the standard solely. But the more important question is actually: Are the compilers backward compatible accordingly? For real world scenarios, that can likely be relevant for the case of non-standard extension usage for instance... – Secundi Jan 14 '21 at 12:26

1 Answers1

3

For reference, this is the C++03 version of §14.6.4.2 [temp.dep.candidate] "Candidate functions":

For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:

  • For the part of the lookup using unqualified name lookup (3.4.1), only function declarations with external linkage from the template definition context are found.
  • For the part of the lookup using associated namespaces (3.4.2), only function definitions with external linkage found in either the template definition context or the template instantiation context are found.

If the call would be ill-formed or would find a better match had the lookup within the associated namespaces considered all the function declarations with external linkage introduced in those namespaces in all translation units, not just considering those declarations found in the template definition and template instantiation contexts, then the program has undefined behaviour.

You can make some example code that would be well defined in C++03, but not C++11:

#include <iostream>

void print(short x) {
    std::cout << x;
}

static void print(long x) {
    std::cout << x;
}

template<typename T>
void print_twice(T x) {
    print(x);
    print(x);
}

int main() {
    print_twice(0);
    // C++03: `void print(long)` does not have external linkage so is not considered.
    //        Calls `void print(short)` twice
    
    // C++11: Both `void print(long)` and `void print(short)` are viable,
    //        but neither is better so it is ambiguous (compile time error)
}

(Though clang and gcc don't seem to implement the C++03 version of ADL, so this would never come up when compiling with those compilers at least)

Artyer
  • 31,034
  • 3
  • 47
  • 75
  • getting same error in both c++11 and c++03. "error: call of overloaded 'print(int&)' is ambiguous" – a learner Jan 15 '21 at 03:25
  • 1
    @alearner Yes because most compilers never implemented this properly, and the standard changed to match what they actually did in C++11. Pedantically, the compilers are wrong for not being able to compile it in C++03 mode. – Artyer Jan 15 '21 at 08:28