9
\$\begingroup\$

I have a need to process URIs in one of my applications, sometimes from 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.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked May 12, 2014 at 9:05
\$\endgroup\$

1 Answer 1

13
\$\begingroup\$

I would follow the way user-defined literals are used in the C++14 standard library: put them in a 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.

answered May 12, 2014 at 9:37
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.