3

I have a function for case insensitive comparison of strings which uses std::lexicographical_compare with custom comparator.

However i would like to be able to compare strings, string_views and const char* between each other, for maximum convenience and efficiency.

So i was thinking: What if i make a template, std::string has begin/end, std::string_view has begin/end, ... but const char* doesn't, not even in a form of non-member function.

So it is ok to define own begin/end overloads like this

namespace std {
    const char * begin(const char* str) { return str; }
    const char * end(const char* str) { return str + strlen(str); }
}

so that then i can compare everything with everything by

std::lexicographical_compare(std::begin(a), std::end(a), std::begin(b), std::end(b), icomp );

?

If not, how else could i solve my problem?

Youda008
  • 1,788
  • 1
  • 17
  • 35
  • 5
    You never should put something into the `std` namespace. Use your own namespace instead. – πάντα ῥεῖ Oct 26 '18 at 15:51
  • 1
    Ahh yes, I remember the controversy when Bjarne Stroustrup first started using "legit" in the standard to talk about defined behavior. But in all seriousness, you should probably pick a more descriptive word for your title. – scohe001 Oct 26 '18 at 15:52
  • 1
    @πάνταῥεῖ There are [a few cases](https://en.cppreference.com/w/cpp/language/extending_std) where you can declare in `namespace std`. – François Andrieux Oct 26 '18 at 15:53
  • 1
    The only things you may add to the `std` namespace are tempate specializations. – Jesper Juhl Oct 26 '18 at 15:54
  • 4
    @Youda008 Just make the function take a `std::string_view`. Then it works with a `std::string`, `std::string_view`, `const char *`, or any class that provides an `operator string_view`.. – NathanOliver Oct 26 '18 at 15:55
  • 1
    you can easily get a `string_view` to a `const char *` I think this is one intended use of `string_view` (which has `begin` and `end`) – 463035818_is_not_an_ai Oct 26 '18 at 15:56
  • Another alternative is to provide `begin()` and `end()` in your own namespace and then bring `std` by using directive – Slava Oct 26 '18 at 15:56

1 Answers1

10

No, this is not legal, because const char * is not a user-defined type.

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited

[namespace.std/1]

You can instead declare those in some other namespace, such as ::

const char * begin(const char* str) { return str; }
const char * end(const char* str) { return str + strlen(str); }

And use them with unqualified calls

std::lexicographical_compare(begin(a), end(a), begin(b), end(b), icomp );

Additionally, in C++20, it will be even more restrictive, permitting only class templates specialisations for program-defined types

Unless otherwise specified, the behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std.

Unless explicitly prohibited, a program may add a template specialization for any standard library class template to namespace std provided that (a) the added declaration depends on at least one program-defined type and (b) the specialization meets the standard library requirements for the original template.

[namespace.std]

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • 2
    `std::begin` also isn't a class template. Note that there is a breaking change going to C++20 where function specializations will no longer be allowed as well: https://stackoverflow.com/questions/52760580/will-specialization-of-function-templates-in-std-for-program-defined-types-no-lo/52760860#52760860 – NathanOliver Oct 26 '18 at 15:56
  • I personally would not put them in the global namespace either (even though it is allowed). The chance for accidental usage by another developer is high. I would put in my own name space and make its usage explicit. – Martin York Oct 26 '18 at 17:46