In C++ an anonymous namespace is equivalent to:
namespace $$$$ {
//something
}
using namespace $$$$;
Where $$$$ is some kind of unique identifier. Anonymous namespace are then useful for code that should not be seen outside the compilation unit.
So far so good, however recently I started to write some code with templates, such code must be in headers so using anonymous namespaces does not make much sense as the mere inclusion of the header will nullify the isolation effect.
Then the question is, what is the suggested way in this cases? I started using a named namespace called Private. It does not really stop anyone who wants to use the identifiers inside, but at least it reduces the name clashes to id "Private."
Are there better ways? Suggestions?
Stick with your Private namespace (or use the more popular detail). Remember the main idea behind C++ access mechanisms is make it difficult to misuse them, not impossible. Protect yourself against accidents, not malicious attacks.
If you're desperate for that isolation, why not the good old file-static? It was undeprecated:
template <typename T>
static void foo()
{}
int main()
{
foo<char>();
}
Then again, if you only need foo within one translation unit, then presumably you're only including it in a header within that translation unit, and then it doesn't matter whatsoever whether it's "in a header". So, simply do not include the templates in other translation units and you've already largely achieved your goal of isolation.
To really guarantee isolation for all possible instantiations (i.e. including those that you've created within this TU), use static as above or simply document your intent using a detail namespace.
The most usual way to hide implementation of template code within a header is to put the implementation into a namespace called detail.
For example:
namespace cpputil { // my c++ utility library namespace
namespace detail { // implementation details of this libraries headers go here
// a functor private to the library
template<class T>
struct private_functor {
private_functor(const T& t) : _t(t) {}
void write(std::ostream& os) const { _t.write(os); }
private:
const T& _t;
};
// an extension to std::ostream::operator<<
template<class T>
std::ostream& operator<<(std::ostream& os, const private_functor<T>& pf)
{
pf.write(os);
return os;
}
}
/// a public template function that is designed to allow an object to be emitted to a stream
/// returns a function object that calls T::write(std::ostream&) when placed into an
/// output stream
template<class T>
detail::private_functor emit(const T& t) {
return detail::private_functor<T>(t);
}
}
// can be used like this:
int main() {
struct S {
void write(std::ostream& os) const { os << "{I am an S}"; }
};
std::cout << cpputil::emit(S) << std::endl;
return 0;
}
Related
Lets say I have a class Customer in namespace Data. Using boost, I know I can convert this into valid JSON by declaring a function with the signature: void tag_invoke( const value_from_tag&, value& jv, Customer const& c ).
However, in all of the examples in the boost documentation, it appears that this tag_invoke function must reside in the Data namespace, i.e. the same namespace as Customer.
I would like to know if it is possible to have something like the following:
namespace FileIO
{
void tag_invoke( const value_from_tag&, value& jv, Data::Customer const& c );
{
jv = {
{ "id", c.id },
{ "name", c.name },
{ "late", c.late }
};
}
}
namespace Network
{
void tag_invoke( const value_from_tag&, value& jv, Data::Customer const& c )
{
jv = {
{ "id", c.id },
{ "late", c.late }
};
}
}
In other words, have two different implementations of the value conversion, where the current namespace would determine which one gets used. I've not had any success getting it working, being met with various "no matching call to value_from_impl" errors.
In case it helps, my CMake setup is such that Data, FileIO, and Network are all separate targets, where both FileIO and Network are linked to/depend Data, but not to each other, and Data depends on no other libraries.
Any advice would be appreciated
Tag invoke is a more useful implementation of the old-fashioned ADL customization points. But it still heavily uses ADL. That means that associated namespaces are considered for overload resolution.
See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf for rationale.
You can declare unrelated overloads in other namespaces but,
best case that namespace is not associated, and the overload is ignored
worst case, that namespace is also associated, and the call becomes ambiguous.
In case it helps, my CMake setup is such that Data, FileIO, and Network are all separate targets, where both FileIO and Network are linked to/depend Data, but not to each other, and Data depends on no other libraries.
That sounds like you have isolated source (translation units). You can define different customization points locally in those TUs. Make (doubly) sure they have internal linkage, so that you don't risk ODR violation. E.g.
namespace Data
{
namespace { // anonymous namespace for file static (no external linkage)
void tag_invoke( const value_from_tag&, value& jv, Customer const& c );
{
// ...
};
}
}
Alternative
Alternatively, you can use tagged wrappers, a bit like manipulators:
Live On Coliru
#include <boost/json.hpp>
#include <boost/json/src.hpp>
#include <iostream>
namespace json = boost::json;
template <typename T> struct UPPERCASE {
T const& ref;
UPPERCASE(T const& ref) : ref(ref) {}
};
namespace Data {
struct Customer {
int id;
std::string name;
bool late;
friend void tag_invoke(json::value_from_tag,json::value&jv, Customer const& c) {
jv = {{"id", c.id}, {"name", c.name}, {"late", c.late}};
}
friend void tag_invoke(json::value_from_tag, json::value& jv, UPPERCASE<Customer> const& c) {
jv = {{"ID", c.ref.id}, {"NAME", c.ref.name}, {"LATE", c.ref.late}};
}
};
} // namespace Data
int main() {
Data::Customer const c{1, "One", true};
std::cout << json::value_from(c) << "\n";
std::cout << json::value_from(UPPERCASE(c)) << "\n";
}
Prints
{"id":1,"name":"One","late":true}
{"ID":1,"NAME":"One","LATE":true}
I'm looking for an official (or at least semi-official) way of exposing my operators in my standard-like library.
For example, I implemented a string literal operator for int128 so that way I can write 128 bit integers at compile time. So far, when I implemented operators, I would just put them outside of my namespace to make them all work without a using namespace snapdev which would be bad because that would bring everything from that namespace and I sure don't want that.
For literals, I've seen that you can use a namespace literals sub-namespace as in the chrono library.
Now, I have many classes that have a corresponding ostream operator like in my matrix implementation:
template<class E, class S, class T, class SIZE>
std::basic_ostream<E, S> & operator << (std::basic_ostream<E, S> & out, snapdev::matrix<T, SIZE> const & m)
{
...
}
Finally, I have a C++ extension to the struct timespec in order to add or subtract or compare values found in a timespec structure. I defined inline operators outside of my namespace ("as usual") but I'd like to fix that and move those operators inside a sub-namespace (like the above for literals).
Is there a convention for this one in the C++ standard library or boost?
The conventions that work well for user-defined literals (either putting them in the global namespace, or in a nested namespace which needs to be manually imported with using namespace) don't work that well for other operators.
Operators (other than UDL) should either be declared where ADL can reach them (i.e. in the same namespace as the parameter types - which you shouldn't do if the namespace is not under your control), or, if they're in a different namespace, imported individually using using ...::operator...; (not using namespace, see below).
When you try to declare them in the global namespace, they might be shadowed by operators in nested namespaces:
namespace X
{
struct A {};
}
void operator+(X::A, X::A) {}
namespace Z
{
struct B {};
void operator+(B, B) {}
void foo()
{
X::A{} + X::A{}; // error: invalid operands to binary expression ('X::A' and 'X::A')
}
}
The same thing happens (interestingly) when you put them in a nested namespace and try to using namespace it:
namespace X
{
struct A {};
}
namespace Y
{
void operator+(X::A, X::A) {}
}
namespace Z
{
struct B {};
void operator+(B, B) {}
void foo()
{
using namespace Y;
X::A{} + X::A{}; // error: invalid operands to binary expression ('X::A' and 'X::A')
}
}
This doesn't compile, because apparently using namespace works "as if [the names] were declared in the nearest enclosing namespace which contains both the using-directive and [target namespace]" (i.e. in this case in the global namespace).
I just noticed this. I don't know why this is the case, if i use one element from a namespace i don't want anything else to be accessible without having to use the namespace. For example here, this code is valid:
namespace Test
{
struct Magic
{
int poof;
};
struct Magic2
{
int poof;
};
int Alakazam(const Magic& m)
{
return m.poof;
}
int Alakazam(const Magic2& m)
{
return m.poof;
}
};
using Magic = Test::Magic;
int main()
{
Alakazam(Magic()); // valid
Alakazam(Test::Magic2()); // valid
Test::Alakazam(Magic()); // what i want to only be valid
Test::Alakazam(Test::Magic2()); // this too
}
Any reasoning behind this? Does the spec state that this has to be true?
As suggested by immbis in the comment, this is defined by the standard:
3.4.2: Argument dependent name lookup
When the postfix-expression in a function call is an unqualified-id, other namespaces not considered during the usual
unqualified lookup may be searched, and in those namespaces,
namespace-scope friend function or function template declarations not
otherwise visible may be found. These modifications to the search
depend on the types of the arguments (and for template template
arguments, the namespace of the template argument).
...
If you want to defeat this mecanism, you have to use nested namespace like this, but it's tricky:
namespace Test
{
struct Magic
{
int poof;
};
struct Magic2
{
int poof;
};
namespace Test2 { // use a nested namespace that will not be searched autoamtically
int Alakazam(const Magic& m)
{
return m.poof;
}
int Alakazam(const Magic2& m)
{
return m.poof;
}
}
using namespace Test2; // but give some access to the enclosing namespace
};
Live Demo : Then, your two first calls will not be valid any longer. However, the last call in your example is still possible: you can't prevent the use of fully qualified names outside of the namespace.
I am trying to create my own enum-based error category and want my enum with error codes to be defined inside some namespace. Much to my surprise this prevents the automatic conversion from values of my enum into std::error_code (such conversion works if the enum is defined in the global namespace).
#include <system_error>
namespace NS { enum class X {a,b,c}; }
using NS::X;
class X_category : public std::error_category
{
public:
virtual const char *name() const noexcept override { return "X"; }
virtual std::string message(int ev) const override { return ""; }
};
inline const std::error_category& X_category()
{
static class X_category c; return c;
}
template<> struct std::is_error_code_enum<X> : public std::true_type{};
inline std::error_code make_error_code(X result)
{
return std::error_code(static_cast<int>(result), X_category());
}
int main()
{
std::error_code e = X::a; // does not work !!
}
Am I missing something in my code above (related to overloading resolution rules perhaps) to make it work? Or do the enums for std::is_error_code_enum<> can only be defined inside a global namespace??
EDIT. My compiler (MSVC2013) does not complain about it but it seems the specialization of std::is_error_code_enum<> must be done inside std namespace. Also I added noexcept keyword on name() method to make the code even more C++11 compliant (MSVC2013 won't understand noexcept, but MSVC2015 will).
EDIT2. According to C++11 14.7.3.2 [temp.expl.spec]:
An explicit specialization shall be declared in a namespace enclosing the specialized template.
So it is not necessary to put specialization of std::is_error_code_enum<> inside an std namespace. MSVC compiles it correctly but GCC complains which is actually a bug in GCC since GCC acts by old C++03 rules which were more restrictive.
The constructor template from error_code is indeed considered in overload resolution - you correctly specialized is_error_code. The problem is the ADL in this line in the definition of error_codes constructor template:
*this = make_error_code(__e);
ADL does not consider the global namespace because X was only defined in NS, not the global one. [basic.lookup.argdep]/(2.3):
If T is an enumeration type, its associated namespace is the
innermost enclosing namespace of its declaration. [..]
The using declaration doesn't change this. [basic.lookup.argdep]/2:
The sets of namespaces and classes is determined entirely by the types
of the function arguments (and the namespace of any template template
argument).
Typedef names and using-declarations used to specify the types do not contribute to this set.
To fix this add your make_error_code to NS:
namespace NS {
inline std::error_code make_error_code(X result)
{
return std::error_code(static_cast<int>(result), X_category());
}
}
Demo.
I believe the problem is that most of that setup code needs to be inside a namespace. This code compiles and runs for me in ideone:
#include <system_error>
#include <iostream>
namespace NS {
enum X {a,b,c};
class X_category : public std::error_category
{
public:
virtual const char *name() const noexcept override { return "X"; }
virtual std::string message(int ev) const override { return "M"; }
};
inline std::error_code make_error_code(X result)
{
return std::error_code(static_cast<int>(result), X_category());
}
}
namespace std {
template<> struct is_error_code_enum<NS::X> : public true_type{};
}
int main()
{
std::cout << NS::X::a;
std::error_code e = NS::X::a;
std::cout << e.value();
}
Unfortunately I still can't make much sense out of system_error, so I can't explain why, for instance, using an enum class instead of just a plain enum gives me an unspecified runtime error.
I am writing a namespace that requires certain functions inside to have access to a particular variable (also declared within the namespace). Normally when I do this, I have the variable declared in the .cpp file to prevent outside access to it.
.h
namespace Example
{
int myFunc();
}
.cpp
namespace Example
{
int hiddenVar;
int myFunc()
{
.. do something with hiddenVar
return someValue;
}
}
My problem is that I need to define a template function that requires access to this hidden variable. Unfortunately since the body of the template function must be defined in the header file it wont have access to the variable hidden in the .cpp.
.h
namespace Example
{
template< typename T >
void myFunc( const T& myT )
{
.. do something with hiddenVar // doesnt know what hiddenVar is
}
}
.cpp
namespace Example
{
int hiddenVar;
}
Is there anyway to have a variable hidden within a namespace while giving a template function in the header access to it?
.h:
namespace Example
{
int * get_hiddenVar();
template< typename T >
void myFunc( const T& myT )
{
int * hiddenVarPtr = get_hiddenVar();
.. do something with *hiddenVarPtr
}
}
.cpp
namespace Example
{
int hiddenVar=0;
int * get_hiddenVar()
{
return &hiddenVar;
}
}
You cannot do this directly, but you can use a function. Since hiddenVar does not depend on the template parameters, you can do this:
.h
namespace Example
{
void Function(); // Use the right function prototype here, of course,
// as long as it does not depend on T
template<typename T>
void myFunc(const T& myT)
{
//...
Function();
//...
}
}
.cpp
namespace Example
{
int hiddenVar;
void Function()
{
// Do something with hiddenVar
}
}
If your use of hiddenVar depends on T, of course, you are out of luck.
Put it in a nested namespace called 'Details' and stop worrying.
'Hiding' a variable using namespaces and private etc are not security-constructs, but there to facilitate better code.