Допустим, у меня есть класс, который переносит строковый литерал:
template <size_t N>
class literal {
public:
constexpr literal(const char(&s)[N+1]) : wrapped_(s) {}
constexpr const char * c_str() const { return wrapped_; }
constexpr size_t size() const { return N; }
private:
const char (&wrapped_)[N+1];
};
template <size_t N>
literal<N-1> make_literal(const char (&s)[N]) { return literal<N-1>(s); }
Теперь я хотел бы, чтобы экземпляры этого типа переносимой строки были преобразованы обратно в const char[N]
неявно, вКстати, я все еще могу получить доступ к его размеру. Я хотел бы иметь возможность сделать что-то вроде:
template <size_t N>
void foo(const char(&s)[N]) {
std::cout << N << ": " << s << std::endl;
}
int main() {
constexpr auto s = make_literal("testing");
foo(s);
}
Моя цель состоит в том, чтобы иметь одну функцию, определенную для foo()
, которая может принимать фактические строковые литералы, а также переносимые литералы. Я попытался добавить пользовательский оператор преобразования в определение класса:
using arr_t = char[N+1];
constexpr operator const arr_t&() const { return wrapped_; }
Но с помощью clang это дает мне следующее:
шаблон кандидата игнорируется: не может быть найдено'const char [N]' против 'const literal <7>'
Если я изменю вызов на foo()
на следующее, это будет работать:
foo((const char(&)[8])s);
. .. что означает, что оператор преобразования работает , но не в контексте вывода аргументов шаблона. Есть ли способ, которым я могу сделать эту работу, не определяя foo()
специально для получения обернутого литерала?