patterncppModerate
User defined string literals and namespace use
Viewed 0 times
literalsuserandusenamespacestringdefined
Problem
I have a need to process URIs in one of my applications, sometimes from
My API:
Client code:
I tried defining the string conversion operator within the
My question:
Does this clash with the "compiler searches for operators in the namespace of the object it applies to" rule (like it would for an
What is the best practice or policy to use here? Import the namespace / operator in client code, or pollute the global namespace (like I did)?
I am using CLang 5.1 on OS X.
const char[] literals.My API:
namespace net {
class uri { ... }; // contains decomposed URI (path, parameters, etc)
uri parse_uri(const std::string& uri_str); // parse string and return uri instance
}
// within global namespace (this is what the question is about):
uri operator "" _uri(const char*str, const unsigned long size)
{
return net::parse_uri(std::string{str, str + size});
}Client code:
auto x = "/static/path/here/image.jpg"_uri;I tried defining the string conversion operator within the
net namespace, but (disimilar to other operators) it seems I have to explicitly specify access to it in client code (with using namespace net; for example).My question:
Does this clash with the "compiler searches for operators in the namespace of the object it applies to" rule (like it would for an
operator+(uri&, uri&) for example)? (As a rule of thumb, I assume the problem is with my code, not the compiler).What is the best practice or policy to use here? Import the namespace / operator in client code, or pollute the global namespace (like I did)?
I am using CLang 5.1 on OS X.
Solution
I would follow the way user-defined literals are used in the C++14 standard library: put them in a
Then, a client code could use your literal with the following code:
I actually slightly simplified the way user-defined literals are used in the standard library for your example: there are actually nested
literals subnamespace that can be imported by the user. This subnamespace would be inline so that it can be imported alone, or automatically imorted when the namescape net is imported:namespace net {
class uri { ... }; // contains decomposed URI (path, parameters, etc)
uri parse_uri(const std::string& uri_str); // parse string and return uri instance
inline namespace literals
{
uri operator "" _uri(const char*str, const unsigned long size)
{
return net::parse_uri(std::string{str, str + size});
}
}
}Then, a client code could use your literal with the following code:
int main()
{
// Import only the literal, not the rest of net
using namespace net::literals;
auto x = "/static/path/here/image.jpg"_uri;
}I actually slightly simplified the way user-defined literals are used in the standard library for your example: there are actually nested
inline namespaces in namespace literals so that a more precise selection of related literals can be done if needed (for example, import only the std::chrono-related literals). Since you have only one literal, you don't need to have so many nested namespaces, but you can still add them later if needed.Code Snippets
namespace net {
class uri { ... }; // contains decomposed URI (path, parameters, etc)
uri parse_uri(const std::string& uri_str); // parse string and return uri instance
inline namespace literals
{
uri operator "" _uri(const char*str, const unsigned long size)
{
return net::parse_uri(std::string{str, str + size});
}
}
}int main()
{
// Import only the literal, not the rest of net
using namespace net::literals;
auto x = "/static/path/here/image.jpg"_uri;
}Context
StackExchange Code Review Q#49502, answer score: 13
Revisions (0)
No revisions yet.