Como determinar a versão do padrão C ++ usado pelo compilador?

115

Como você determina qual versão do padrão C ++ é implementada por seu compilador? Pelo que eu sei, abaixo estão os padrões que conheço:

  • C ++ 03
  • C ++ 98
Jasonline
fonte
3
Você marcou este c ++ , mas dois dos três padrões listados não são padrões C ++. Em quais idiomas você está interessado?
Rob Kennedy
1
E a pergunta foi feita apenas alguns minutos atrás. ( stackoverflow.com/questions/7132440/… )
Mat de
1
@Mat: Posto e encerrado porque a pergunta era uma porcaria e tinha algum outro absurdo arbitrário em cima dela. Eu reenviei em uma forma decente. Ficaria feliz em fechar este se parecer que o original será consertado e revivido, mas não estou prendendo a respiração.
Lightness Races in Orbit de
1
@Mat: Bem, a melhor resposta não é uma lista estática de compiladores, mas um meio de determinar por si mesmo o que está em uso. Então aí está.
Lightness Races in Orbit de
1
@Als: Será em breve. Eu prometo. Além disso, a c++-faqtag não tem nenhum pré-requisito real "número de vezes solicitado" que você tenha que passar; é mais sobre o formato e a generalidade da coisa.
Lightness Races in Orbit de

Respostas:

13

Pelo que sei, não há uma maneira geral de fazer isso. Se você olhar os cabeçalhos das bibliotecas de suporte de plataforma cruzada / compilador múltiplo, você sempre encontrará muitas definições que usam construções específicas do compilador para determinar tais coisas:

/*Define Microsoft Visual C++ .NET (32-bit) compiler */
#if (defined(_M_IX86) && defined(_MSC_VER) && (_MSC_VER >= 1300)
     ...
#endif

/*Define Borland 5.0 C++ (16-bit) compiler */
#if defined(__BORLANDC__) && !defined(__WIN32__)
     ...
#endif

Você provavelmente terá que fazer essas definições sozinho para todos os compiladores que usar.

RED SOFT ADAIR
fonte
1
Não é a minha resposta esperada, mas acho que não há uma maneira universal de descobrir.
jasonline
248

Do Bjarne Stroustrup C ++ 0x FAQ :

__cplusplus

Em C ++ 0x a macro __cplusplusserá definida com um valor diferente (maior que) do atual 199711L.

Embora isso não seja tão útil quanto você gostaria. gcc(aparentemente por quase 10 anos) tinha esse valor definido como 1, descartando um grande compilador, até que foi corrigido quando o gcc 4.7.0 foi lançado .

Estes são os padrões C ++ e qual valor você deve esperar em __cplusplus:

  • C ++ pré-C ++ 98: __cplusplusé1 .
  • C ++ 98: __cplusplusé199711L .
  • C ++ 98 + TR1: Lê-se como C ++ 98 e não há como verificar se eu conheço.
  • C ++ 11: __cplusplusé201103L .
  • C ++ 14: __cplusplusé201402L .
  • C ++ 17: __cplusplusé 201703L.

Se o compilador for mais antigo gcc, precisamos recorrer a hackeamentos específicos do compilador (veja uma macro de versão, compare-a a uma tabela com recursos implementados) ou use Boost.Config (que fornece macros relevantes ). A vantagem disso é que podemos escolher recursos específicos do novo padrão e escrever uma solução alternativa se o recurso estiver ausente. Freqüentemente, isso é preferido em vez de uma solução de atacado, pois alguns compiladores afirmam implementar C ++ 11, mas oferecem apenas um subconjunto dos recursos.

O Stdcxx Wiki hospeda uma matriz abrangente para suporte do compilador de recursos C ++ 0x (se você se atrever a verificar os recursos você mesmo).

Infelizmente, uma verificação mais refinada de recursos (por exemplo, funções de biblioteca individuais como std::copy_if) só pode ser feita no sistema de compilação de seu aplicativo (execute o código com o recurso, verifique se ele compilou e produziu resultados corretos - autoconfé a ferramenta de escolha se usar esta rota).

pmr
fonte
Não parece que os fornecedores de compiladores estão atualizando isso - talvez eles estejam esperando até que estejam totalmente em conformidade com o padrão? ( Stackoverflow.com/q/14131454/11698 )
Richard Corden
2
@prnr: Isso pode ser verdade, mas cabe ao usuário que fez a pergunta decidir qual resposta aceitar. No momento em que a resposta atualmente marcada como aceita foi postada, ela estava correta, portanto o autor da postagem original a aceitou. Esse usuário pode decidir alterar a resposta aceita, mas pode não estar mais ativo no site. Consulte: meta.stackexchange.com/questions/120568/…
Dan Korn
3
vs2017 dá o valor de __cplusplus 199711
Al Mamun
5
@AlMamun Microsoft parcialmente corrigido __cplusplusapenas no VS 15.7. Veja o blog da equipe do Visual C ++
Ivan_Bereziuk
1
O link para o FAQ está quebrado.
brainplot
38

Por favor, execute o seguinte código para verificar a versão.

#include<iostream>

int main() {
    if (__cplusplus == 201703L) std::cout << "C++17\n";
    else if (__cplusplus == 201402L) std::cout << "C++14\n";
    else if (__cplusplus == 201103L) std::cout << "C++11\n";
    else if (__cplusplus == 199711L) std::cout << "C++98\n";
    else std::cout << "pre-standard C++\n";
}
Deepanshu
fonte
8
É engraçado, porque nos estúdios visuais o valor de __cplusplus é 199711L e o código que você postou retornou c ++ 98, entretanto, usei recursos do c ++ 14 incluindo modelos de variáveis ​​e decltype (auto). É possível que a versão errada da macro tenha sido implementada?
Colin Hicks
2
Consulte: devblogs.microsoft.com/cppblog/… (TLDR: especificar o sinalizador /Zc:__cplusplus)
Daan Timmer
@DaanTimmer Estou confuso com aquele artigo, parece assumir conhecimento de como usar a /Zc:__cplusplusflag. Não posso simplesmente std::cout << /Zc:__cplusplus;porque dois pontos e barras não podem fazer parte dos nomes das variáveis, é claro. Você consegue explicar como fazer isso? Obrigado.
A__
7

Dependendo do que você deseja alcançar, Boost.Config pode ajudá-lo. Ele não fornece detecção da versão padrão, mas fornece macros que permitem verificar o suporte de linguagem / recursos de compilador específicos.

Björn Pollex
fonte
3
Verificar os recursos é provavelmente uma ideia melhor do que verificar as versões padrão. Poucos compiladores suportam tudo de um padrão, mas se todos eles suportam o número limitado de recursos de que você precisa, então realmente não importa se o restante dos recursos de um determinado padrão estão implementados e funcionando corretamente.
Rob Kennedy
4

__cplusplus

Em C ++ 0x, a macro __cplusplus será definida com um valor diferente (maior que) do atual 199711L.

C ++ 0x FAQ por BS

Vinzenz
fonte
0

Depois de um rápido google :

__STDC__e __STDC_VERSION__veja aqui

Tor Valamo
fonte
Se __STDC__está definido e qual é seu valor, são definidos pela implementação em C ++.
Rob Kennedy
@Rob: Sim, é. @Tor: Tentei no VC ++ 2005, mas diz que STDC é um identificador não declarado. No entanto, ele é listado como uma dessas macros predefinidas. No entanto, STDC_VERSION não existe.
jasonline
Isso informa a versão da linguagem de programação C suportada pelo compilador. Não diz nada sobre a versão da linguagem C ++ que é compatível.
Dan Molding
0

Normalmente você deve usar __cplusplusdefine para detectar c ++ 17, mas por padrão o compilador da Microsoft não define essa macro corretamente, consulte https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - você precisa para modificar as configurações do projeto para incluir a /Zc:__cpluspluschave, ou você pode usar uma sintaxe como esta:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
TarmoPikaro
fonte