Допустимо ли определять std :: begin для const char *?

У меня есть функция для сравнения строк без учета регистра, которая использует std::lexicographical_compare с настраиваемым компаратором.

Однако я хотел бы иметь возможность сравнивать strings, string_views и const char* между собой для максимального удобства и эффективности.

Итак, я подумал: что, если я создам шаблон, std::string имеет _6 _ / _ 7_, std::string_view имеет _9 _ / _ 10_, ... но const char* нет, даже в виде функции, не являющейся членом.

Так что можно определять собственные _12 _ / _ 13_ перегрузки следующим образом

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

так что тогда я могу сравнивать все со всем

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

?

Если нет, то как еще я могу решить свою проблему?


person Youda008    schedule 26.10.2018    source источник
comment
Никогда не следует помещать что-либо в пространство имен std. Вместо этого используйте собственное пространство имен.   -  person πάντα ῥεῖ    schedule 26.10.2018
comment
Ах да, я помню споры, когда Бьярн Страуструп впервые начал использовать законное в стандарте, чтобы говорить об определенном поведении. Но если серьезно, вам, вероятно, следует выбрать более описательное слово для своего заголовка.   -  person scohe001    schedule 26.10.2018
comment
@ πάνταῥεῖ Существует несколько случаев, в которых вы можете объявить в namespace std.   -  person François Andrieux    schedule 26.10.2018
comment
Единственное, что вы можете добавить в пространство имен std, - это временные специализации.   -  person Jesper Juhl    schedule 26.10.2018
comment
@ Youda008 Просто заставьте функцию взять std::string_view. Затем он работает с std::string, std::string_view, const char * или любым другим классом, который предоставляет operator string_view ..   -  person NathanOliver    schedule 26.10.2018
comment
вы можете легко получить string_view на const char *. Я думаю, это одно из предполагаемых вариантов использования string_view (в котором есть begin и end)   -  person 463035818_is_not_a_number    schedule 26.10.2018
comment
Другой альтернативой является предоставление begin() и end() в вашем собственном пространстве имен, а затем использование std с помощью директивы   -  person Slava    schedule 26.10.2018


Ответы (1)


Нет, это незаконно, потому что const char * не является определяемым пользователем типом.

Поведение программы C ++ не определено, если она добавляет объявления или определения в пространство имен std или в пространство имен в пространстве имен std, если не указано иное. Программа может добавить специализацию шаблона для любого стандартного шаблона библиотеки в пространство имен std только в том случае, если объявление зависит от определяемого пользователем типа, а специализация соответствует требованиям стандартной библиотеки для исходного шаблона и не запрещена явным образом.

[namespace.std/1]

Вместо этого вы можете объявить их в другом пространстве имен, например ::

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

И используйте их с неквалифицированными звонками

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

Кроме того, в C ++ 20 он будет еще более строгим, разрешая только специализацию шаблонов классов для программно определенных типов.

Если не указано иное, поведение программы C ++ не определено, если она добавляет объявления или определения в пространство имен std или в пространство имен в пространстве имен std.

Если явно не запрещено, программа может добавить специализацию шаблона для любого шаблона класса стандартной библиотеки в пространство имен std при условии, что (а) добавленное объявление зависит по крайней мере от одного типа, определенного программой и (б) специализация соответствует требованиям стандартной библиотеки для оригинальный шаблон.

[namespace.std]

person Caleth    schedule 26.10.2018
comment
std::begin также не является шаблоном класса. Обратите внимание, что есть критическое изменение, касающееся C ++ 20, где специализация функций также больше не будет разрешена: stackoverflow.com/questions/52760580 / - person NathanOliver; 26.10.2018
comment
Лично я бы тоже не стал помещать их в глобальное пространство имен (хотя это и разрешено). Вероятность случайного использования другим разработчиком высока. Я бы добавил свое собственное пространство имен и сделал бы его использование явным. - person Martin York; 26.10.2018