Tuesday, June 25, 2019

c++ - Unnamed/anonymous namespaces vs. static functions

There is one edge case where static has a surprising effect(at least it was to me). The C++03 Standard states in 14.6.4.2/1:



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 declarations with external linkage found in either the template definition context or the template instantiation context are found.


...



The below code will call foo(void*) and not foo(S const &) as you might expect.


template 
int b1 (T const & t)
{
foo(t);
}
namespace NS
{
namespace
{
struct S
{
public:
operator void * () const;
};
void foo (void*);
static void foo (S const &); // Not considered 14.6.4.2(b1)
}
}
void b2()
{
NS::S s;
b1 (s);
}

In itself this is probably not that big a deal, but it does highlight that for a fully compliant C++ compiler (i.e. one with support for export) the static keyword will still have functionality that is not available in any other way.


// bar.h
export template
int b1 (T const & t);
// bar.cc
#include "bar.h"
template
int b1 (T const & t)
{
foo(t);
}
// foo.cc
#include "bar.h"
namespace NS
{
namespace
{
struct S
{
};
void foo (S const & s); // Will be found by different TU 'bar.cc'
}
}
void b2()
{
NS::S s;
b1 (s);
}

The only way to ensure that the function in our unnamed namespace will not be found in templates using ADL is to make it static.


Update for Modern C++


As of C++ '11, members of an unnamed namespace have internal linkage implicitly (3.5/4):



An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage.



But at the same time, 14.6.4.2/1 was updated to remove mention of linkage (this taken from C++ '14):



For a function call where the postfix-expression is a dependent name, 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 from the template definition context are found.


  • For the part of the lookup using associated namespaces (3.4.2), only function declarations found in either the template definition context or the template instantiation context are found.




The result is that this particular difference between static and unnamed namespace members no longer exists.

No comments:

Post a Comment

plot explanation - Why did Peaches' mom hang on the tree? - Movies & TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...