String constante e estática em uma template de classe [RESOLVIDO]

1. String constante e estática em uma template de classe [RESOLVIDO]

M.
XProtoman

(usa Fedora)

Enviado em 24/12/2016 - 02:37h

Boa noite a todos,

Recentemente tive a necessidade de ter uma string constante e estática em uma template de classe, porém estou tendo problemas:
#include <iostream>

template <typename Teste>
class String
{
public:
static const Teste mensagem = {(typename Teste::value_type)'o', (typename Teste::value_type)'i'};
};

int main()
{
std::cout << (String <std::string>::mensagem) << std::endl;
return 0;
}


Resultado:
string.cpp: In instantiation of ‘class String<std::__cxx11::basic_string<char> >’:
string.cpp:12:37: required from here
string.cpp:7:22: error: in-class initialization of static data member ‘const std::__cxx11::basic_string<char> String<std::__cxx11::basic_string<char> >::mensagem’ of non-literal type
static const Teste mensagem = {(typename Teste::value_type)'o', (typename Teste::value_type)'i'};
^~~~~~~~
string.cpp: In instantiation of ‘const std::__cxx11::basic_string<char> String<std::__cxx11::basic_string<char> >::mensagem’:
string.cpp:12:39: required from here
string.cpp:7:22: error: in-class initialization of static data member ‘const std::__cxx11::basic_string<char> String<std::__cxx11::basic_string<char> >::mensagem’ of non-literal type
string.cpp:7:22: error: call to non-constexpr function ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::initializer_list<_Tp>, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
Makefile:151: recipe for target 'build-tests' failed
make: *** [build-tests] Error 1


Existe alguma solução?


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 25/12/2016 - 02:47h

Feliz Natal do Salvador do mundo!

As mensagens parecem relativamente óbvias. O valor do membro estático e constante só pode ser atribuído dentro da definição da classe se esse valor for de um tipo integral (inclusive enumerações) e, obviamente, constante.

Outra coisa: aquelas conversões de tipo ao estilo de C são permitidas em C++, mas não são geralmente muito bem vistas, porque eminentemente perigosas, já que inibem verificações sobre conversões suspeitas que o compilador poderia detectar e apontar.

Mas não seria necessária nenhuma conversão explícita. Você está usando um construtor com lista de inicialização, cujos elementos certamente terão tipos conhecidos, relacionados ao tipo de Teste (se isso não existir, a compilação falhará). No seu caso, que usa std::string, os elementos da lista de inicialização têm de ser do tipo char, e o compilador sabe disso, e pode fazer conversões implícitas para você.

Assim sendo, eis como poderia ficar seu código.

#include <iostream>

template <typename Teste>
class String
{
public:
static const Teste mensagem;
};
template <typename Teste> const Teste String<Teste>::mensagem = {'o', 'i'};

int main()
{
std::cout << (String <std::string>::mensagem) << std::endl;
return 0;
}


3. Re: String constante e estática em uma template de classe [RESOLVIDO]

M.
XProtoman

(usa Fedora)

Enviado em 26/12/2016 - 00:36h

paulo1205 escreveu:

Feliz Natal do Salvador do mundo!

As mensagens parecem relativamente óbvias. O valor do membro estático e constante só pode ser atribuído dentro da definição da classe se esse valor for de um tipo integral (inclusive enumerações) e, obviamente, constante.

Outra coisa: aquelas conversões de tipo ao estilo de C são permitidas em C++, mas não são geralmente muito bem vistas, porque eminentemente perigosas, já que inibem verificações sobre conversões suspeitas que o compilador poderia detectar e apontar.

Mas não seria necessária nenhuma conversão explícita. Você está usando um construtor com lista de inicialização, cujos elementos certamente terão tipos conhecidos, relacionados ao tipo de Teste (se isso não existir, a compilação falhará). No seu caso, que usa std::string, os elementos da lista de inicialização têm de ser do tipo char, e o compilador sabe disso, e pode fazer conversões implícitas para você.

Assim sendo, eis como poderia ficar seu código.

#include <iostream>

template <typename Teste>
class String
{
public:
static const Teste mensagem;
};
template <typename Teste> const Teste String<Teste>::mensagem = {'o', 'i'};

int main()
{
std::cout << (String <std::string>::mensagem) << std::endl;
return 0;
}

paulo1205, muito obrigado mais uma vez, não imaginava que houvesse uma solução para esse problema, a forma que você apresentou é perfeita, muito obrigado mesmo. Feliz Natal para você, toda sua família e o pessoal do VOL.



____________________
“Mas nós sabemos que a razão de a maioria estar aqui, é a nossa afinidade com a desobediência!” (Morpheus)






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts