C language linkage typedef & templates - c++

I understand that a template cannot appear inside an extern "C" block, the reason for which is that the name of the instantiated template functions cannot appear once than once using an unmangled name.
However, in the code below, the name of the function is being mangled (so there should be no problem because each instantiation will have a unique name) but still has function type with C language linkage. My question is whether the code below is well formed:
extern "C" using fn_type = void();
template<typename T>
fn_type foo;
int main()
{
fn_type* const p = foo<int>;
p();
}
Edit: it is hard to test if this is conforming just by running it through a compiler because GCC, Clang and MSVC don't distinguish between C++ and C function pointer types.

To me, the standard does not seem 100% clear on this. The only relevant part which mentions templates and linkage is C++11, [temp]§4:
A template name has linkage (3.5). A non-member function template can have internal linkage; any other template name shall have external linkage. Specializations (explicit or implicit) of a template that has internal linkage are distinct from all specializations in other translation units. A template, a template explicit specialization (14.7.3), and a class template partial specialization shall not have C linkage. Use of a linkage specification other than C or C++ with any of these constructs is conditionally-supported, with implementation-defined semantics. [...]
(Emphasis mine)
The paragraph starts with template names having linkage. Then it says "funciton template (notname) can have internal linkage; any other template name shall have external linkage."
To me, this seems to imply referring to the linkage of a template refers to the linkage of the template's name. If that interpretation is correct, then your example is well-formed, as the bolded part would apply to template names as well. Then nothing prevents function template types from having C linkage.
That's how I would interpret the standard.

Related

Argument-dependent lookup of dependent names

This description on cppreference.com says that
The lookup of a dependent name used in a template is postponed until the template arguments are known, at which time [...] ADL examines function declarations with external linkage that are visible from either the template definition context or the template instantiation context.
Contrary to this the following code snippet compiles fine with three compilers (MSVC, clang, gcc):
template <class T>
void CallFoo ()
{
Foo (T ());
}
class Apple {};
int main ()
{
CallFoo<Apple> ();
}
static void Foo (Apple)
{
}
Foo is a dependent name in CallFoo: it depends on template argument T. But the function Foo is found by the compiler despite violating two of the above quoted rules.
The declaration of Foo is not visible from either the definition or instantiation of CallFoo, because it is below both.
Foo has internal linkage.
It is unlikely, that all three compilers have a bug. I might have misunderstood something. Could you elaborate on this?
In C++03, members of anonymous namespaces could have external linkage despite being unnameable in other translation units. It was therefore thought permissible to preclude actual static functions from dependent ADL. In C++11, anonymous namespaces impose internal linkage, so the restriction became unreasonable. However, despite implementations adopting the new behavior and an issue being filed immediately in 2011 (as noted in the comments), the wording remained in two places until N4810 in March 2019.
As for the placement of the function, this is an artifact of functions having multiple points of instantiation, including the end of any translation unit that instantiates them (with slight adjustments for modules in C++20); if instantiating the function template produces different results for different choices, the program is ill-formed, no diagnostic required (as also noted in the comments).

Template dependent name resolution should not find declarations with no linkage?

In the c++ standard [temp.point] it is written:
The instantiation context of an expression that depends on the
template arguments is the set of declarations with external linkage
declared prior to the point of instantiation of the template
specialization in the same translation unit.
Then in [temp.dep.candidate]:
For the part of the lookup using associated namespaces
([basic.lookup.argdep]), only function declarations found in either
the template definition context or the template instantiation context
are found.
Does it means that the following code should fail:
namespace A{
struct S{};
}
template<class T>
void g(T a){
f(a); //f will be found by argument dependent lookup
}
namespace A{
static void f(S); //but f doesn't have external linkage
}
void test(A::S i){
g(i);
}
//point of instantiation of g
//A::f(S) doesn't have external linkage
//=> so it's not in the instantiation context of template g ??
This code actually compiles, so what does this standard paragraph mean?
This is a defect in the standard. Originally addressed in core issue 561, where the committee judged that
Notes from the April, 2006 meeting:
The consensus of the group was [..] that internal-linkage functions should be found by the lookup (although they may result in errors if selected by overload resolution).
Unfortunately the corresponding fix was insufficient, as elaborated in core issue 1258:
C++11 expanded the lookup rules for dependent function calls (17.7.4.2 [temp.dep.candidate] paragraph 1 bullet 2) to include functions with internal linkage; previously only functions with external linkage were considered. However, 17.7.4.1 [temp.point] paragraph 6 still says,
The instantiation context of an expression that depends on the template arguments is the set of declarations with external linkage declared prior to the point of instantiation of the template specialization in the same translation unit.
Presumably this wording was overlooked and should be harmonized with the new specification.
That is, the previous wording of your second quoted paragraph was
For the part of the lookup using associated namespaces (3.4.2), only function declarations with external linkage
found in either the template definition context or the template instantiation context are found.
.. which was amended for C++11, but that change missed your first quote, making it rather pointless. The intent is that functions with internal linkage are not discriminated.

About ODR-violations and template variables

I know that template functions don't suffer of multiple definitions when linking, like member functions defined inside a class, which are inline by default. Also, constexpr objects have internal linkage, but template variables have external linkage (I mean at namespace scope and for C++14 in both cases).
What about?
template<class T>
constexpr T i_am_odr_safe{};
Does i_am_odr_safe have external or internal linkage in C++14? and is it safe regarding multiple-definitions like function templates?
In other words, is i_am_odr_safe odr-safe?
This is core issue 1713, the direction of which IIRC is that this variable template will have external linkage.
And no, this hasn't been resolved yet, which is why LWG decided to plaster inline all over the variable templates in the standard library when it adopted A+B2 of P0604R0.

When does a non-member function template have internal linkage?

C++11 draft, 14.0.4:
A non-member function template can have internal linkage; any other
template name shall have external linkage.
This query is a consequence of separating template declaration and definition. For example, we can write the following in a header file.
template <typename T>
bool operator==(T const & l, T const & r);
In a single source file, destined to become a single translation unit, we write the definition. We also instantiate it, either implicitly or explicitly, in the same translation unit, for type foo.
template <typename T>
bool operator==(T const & l, T const & r)
{
return extract(l) == extract(r); // extract is uninteresting
}
In a second translation unit, which can only see the definition from the header, we attempt to use foo{} == foo{}, that is, to call the operator== which is instantiated elsewhere.
Currently, this "works". The linker patches the two translation units as I hoped it would.
However, if the function template has internal linkage, the link can fail. For example, we can force this by instantiating within an anonymous namespace.
Does the "can" in the spec indicate that the source code controls the linkage (e.g. by namespace {}) or that the compiler is permitted to choose whether the instantiation will have internal or external linkage?
I don't believe there is any undefined behaviour here, but I am struggling to convince myself that the linkage chosen is not an implementation detail. Can I rely on the symbol being visible from other translation units, if it has been instantiated in at least one TU in a context that suggests it will be external?
edit: DR1603 (thanks Eugene Zavidovsky!) contains a recommendation to erase exactly the sentence quoted above, alongside general rationalisation of linkage rules.
Does the "can" in the spec indicate that the source code controls the linkage (e.g. by namespace {}) or that the compiler is permitted to choose whether the instantiation will have internal or external linkage?
This is the code that controls the linkage. A function generated from function template has external linkage, unless it is a static function template or the template is in unnamed namespace (since C++11).
In other words, one would have to explicitly ask for internal linkage.

Static variable inside template function

In C++, if you define this function in header.hpp
void incAndShow()
{
static int myStaticVar = 0;
std::cout << ++myStaticVar << " " << std::endl;
}
and you include header.hpp in at least two .cpp files. Then you will have multiple definition of incAndShow(). Which is expected. However, if you add a template to the function
template <class T>
void incAndShow()
{
static int myStaticVar = 0;
std::cout << ++myStaticVar << " " << std::endl;
}
then you won't have any multiple definition of error. Likewise, two different .cpp calling the function with the same template (e.g. incAndShow<int>()), will share myStaticVar. Is this normal? I'm asking this question, because I do rely on this "feature" (sharing the static variable) and I want to be sure that it is not only my implementation that is doing this.
You can rely on this. The ODR (One Definition Rule) says at 3.2/5 in the Standard, where D stands for the non-static function template (cursive font by me)
If D is a template, and is defined in more than one translation unit, then the last four requirements from the list above shall apply to names from the template’s enclosing scope used in the template definition (14.6.3), and also to dependent names at the point of instantiation (14.6.2). If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.
Of the last four requirements, the two most important are roughly
each definition of D shall consist of the same sequence of tokens
names in each definition shall refer to the same things ("entities")
Edit
I figure that this alone is not sufficient to guarantee that your static variables in the different instantiations are all the same. The above only guarantees that the multiple definitions of the template is valid. It doesn't say something about the specializations generated from it.
This is where linkage kicks in. If the name of a function template specialization (which is a function) has external linkage (3.5/4), then a name that refers to such a specialization refers to the same function. For a template that was declared static, functions instantiated from it have internal linkage, because of
Entities generated from a template with internal linkage are distinct from all entities generated in other translation units. -- 14/4
A name having namespace scope (3.3.6) has internal linkage if it is the name of [...] an object, reference, function or function template that is explicitly declared static -- 3.5/3
If the function template wasn't declared with static, then it has extern linkage (that, by the way, is also the reason that we have to follow the ODR at all. Otherwise, D would not be multiply defined at all!). This can be derived from 14/4 (together with 3.5/3)
A non-member function template can have internal linkage; any other template name shall have external linkage. -- 14/4.
Finally, we come to the conclusion that a function template specialization generated from a function template with external linkage has itself external linkage by 3.5/4:
A name having namespace scope has external linkage if it is the name of [...] a function, unless it has internal linkage -- 3.5/4
And when it has internal linkage was explained by 3.5/3 for functions provided by explicit specializations, and 14/4 for generated specializations (template instantiations). Since your template name has external linkage, all your specializations have external linkage: If you use their name (incAndShow<T>) from different translation units, they will refer to the same functions, which means your static objects will be the same in each occasion.
Just so i understand your question. You are asking if it is normal for each version of the templated function to have its own instance of myStaticVar. (for example: incAndShow<int> vs. intAndShow<float> The answer is yes.
Your other question is, if two files include the header containing the template function, will they still share the static variable for a given T. I would say yes.
The difference when you create the function template is that it has external linkage. The same incAndShow will be accessible from all translation units.
Paraphrasing from C++ standard working draft N2798 (2008-10-04):
14 part 4: a non member function template can have internal linkage, others always have external linkage.
14.8 point 2: every specialization will have its own copy of the static variable.
Your function template should have external linkage unless you declare it in the unnamed namespace or something. So, for each T that you use with your function template, you should get one static variable used throughput the program. In other words, it's OK to rely on having only one static variable in the program for each instantiation of the template (one for T==int, one for T==short, etc).
As an aside, this can lead to weird situations if you define incAndShow differently in different translation units. E.g., if you define it to increment in one file and the decrement in another file (without specifying internal linkage by putting the function into the unnamed namespace) both will end up sharing the same function, which will effectively be chosen at random at compile time (with g++ it depends on the order the object files are given on the command line).
Templates are instantiated as needed, which means that compiler (linker as well in this case?) will make sure that you don't end up with multiple instances of the same template as well as only those instances of templates that you need - in your case only incAndShow<int>() is instantiated and nothing else (otherwise compiler would have to try to instantiate for every type which does not make sense).
So I assume that the same methods it uses to figure out for which type to instantiate template prevents it from instantiating twice for the same type e.g. only one instance of incAndShow<int>()
This is different from non template code.
Yes, it is "normal", but whatever you try to achieve with this "feature" maybe questionable. Try explain why you want to use local static variable, may be we can come up with a cleaner way to do it.
The reason this is normal is because of the way template functions are compiled and linked. Each translation unit (the two .cpp in your case) gets see their own copy of incAndShow and when the program is linked together, the two incAndShow will be merged into one. If you declare your regular function inline in the header file, you'll get similar effect.
Take this example that shows the behaviour is absolutely expected:
#include <iostream>
template <class T> class Some
{
public:
static int stat;
};
template<class T>
int Some<T>::stat = 10;
void main()
{
Some<int>::stat = 5;
std::cout << Some<int>::stat << std::endl;
std::cout << Some<char>::stat << std::endl;
std::cout << Some<float>::stat << std::endl;
std::cout << Some<long>::stat << std::endl;
}
You get: 5 10 10 10 10
The above shows that the change in static variable is only for type "int" and hence in your case you don't see any problem.
templates will only actually be turned into code once they're instantiated (i.e. used)
headers are not to be used for implementation code, but only for declarations