Convenientemente Declarando Strings Compile-Time em C ++
Ser capaz de criar e manipular seqüências de caracteres durante o tempo de compilação em C ++ tem vários aplicativos úteis. Embora seja possível criar strings em tempo de compilação em C ++, o processo é muito incômodo, já que a string precisa ser declarada como uma sequência variadica de caracteres, por exemplo.
using str = sequence<'H', 'e', 'l', 'l', 'o', ', ', 'w', 'o', 'r', 'l', 'd', '!'>;
Operações como concatenação de strings, extração de substrings e muitas outras, podem ser facilmente implementadas como operações em sequências de caracteres.É possível declarar cadeias de tempo de compilação mais convenientemente? Se não, existe uma proposta nos trabalhos que permita a declaração conveniente de cadeias de tempo de compilação?
Por que as abordagens existentes falham?Idealmente, gostaríamos de poder declarar strings em tempo de compilação da seguinte maneira:
// Approach 1
using str1 = sequence<"Hello, world!">;
ou, usando literais definidos pelo usuário,
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
Ondedecltype(str2)
teria umconstexpr
construtor. Uma versão mais confusa da abordagem 1 é possível implementar, aproveitando o fato de que você pode fazer o seguinte:
template <unsigned Size, const char Array[Size]>
struct foo;
No entanto, o array precisaria ter uma ligação externa, então, para que a abordagem 1 funcionasse, teríamos que escrever algo assim:
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string<13, str>;
return 0;
}
Escusado será dizer que isto é muito inconveniente. A abordagem 2 não é realmente possível de implementar. Se tivéssemos que declarar um (constexpr
) operador literal, então como podemos especificar o tipo de retorno? Como precisamos que o operador retorne uma sequência variadica de caracteres, então precisaríamos usar oconst char*
parâmetro para especificar o tipo de retorno:
constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */
Isso resulta em um erro de compilação, porques
não é umconstexpr
. Tentando contornar isso fazendo o seguinte não ajuda muito.
template <char... Ts>
constexpr sequence<Ts...> operator"" _s() { return {}; }
O padrão determina que esse formulário de operador literal específico seja reservado para tipos de ponto flutuante e inteiro. Enquanto123_s
trabalharia,abc_s
não faria. E se nós abandonarmos os literais definidos pelo usuário e usarmos apenas umconstexpr
função?
template <unsigned Size>
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */
Como antes, nos deparamos com o problema que a matriz, agora um parâmetro para oconstexpr
função, já não é umconstexpr
tipo.
Eu acredito que deve ser possível definir uma macro de pré-processador C que leva uma string e o tamanho da string como argumentos, e retorna uma seqüência que consiste nos caracteres da string (usandoBOOST_PP_FOR
, string, array subscritos e similares). No entanto, eu não tenho tempo (ou juros suficientes) para implementar essa macro =)