Estratégia para o OS X e versão de nível inferior da biblioteca C ++ 11?

5

Acho que me encontrei em uma situação em que as coisas estão rapidamente saindo de controle e gostaria de obter algum feedback para selecionar uma maneira de prosseguir.

ANTECEDENTES

Estou trabalhando com uma biblioteca baseada em C ++ 03. A biblioteca é multi-plataforma e suporta vários compiladores. Não há dependências externas ou pré-requisitos (ou seja, não há necessidade de Autotools, Cmake, Boost, etc). Começamos a testar com std=c++11 e descobrimos algumas coisas que precisavam ser corrigidas. Por exemplo, auto_ptr foi preterido, por isso precisávamos mudar para unique_ptr if __cplusplus >= 201103L .

A mudança para unique_ptr foi relativamente fácil, exceto no OS X. O OS X anuncia __cplusplus como 201103L , mas é uma biblioteca de tempo de execução C ++ 11 extremamente deficiente (não vou nem usar o word "standard" nessa sentença). Pior, se alguém construir o LLVM / Clang mais recente a partir de fontes no OS X sem libcxx , as mesmas deficiências existirão porque o novo Clang usa as bibliotecas antigas.

Para resolver o problema de auto_ptr , passamos por alguns obstáculos que terminaram no código a seguir. Embora o código abaixo pareça limpo, o pré-processador está fazendo hora extra para determinar quando deve definir MYLIB_HAVE_UNIQUE_PTR e MYLIB_HAVE_TEMPLATE_ALIAS devido ao OS X.

// The result is MyLib::auto_ptr in both cases
#if defined(MYLIB_HAVE_UNIQUE_PTR) && defined(MYLIB_HAVE_TEMPLATE_ALIAS)
  template<typename T>
    using auto_ptr = std::unique_ptr<T>;
#else
  using std::auto_ptr;
#endif

Agora estamos tentando fornecer a semântica de movimentação protegida em __cplusplus , porque há de duas a cinco classes que seriam beneficiadas. No entanto, o OS X está nos dando problemas novamente porque ele não possui std::move . Eu suspeito que ele vai ter problemas com Rvalues e Rvalue References, também.

Perguntamos aos desenvolvedores da Clang como apresentar testes para std::move em Como para testar std :: move (intersecção de Apple e Clang) . Um dos desenvolvedores da Clang sugeriu que nós criássemos o nosso, mas estou começando a achar que é uma batalha perdida baseada no código-fonte do GNU para move.h . Por exemplo, um rápido grep -IR is_lvalue_reference /usr/include/c++/4.2.1/ não revela resultados.

ESTRATÉGIAS

Acho que nossas escolhas são (1) descartar o suporte para o OS X; (2) tratar o OS X como C ++ 03; (3) rolar nossa própria implementação para perder recursos do C ++ 11 no OS X; ou (4) alternar para Autotools ou Cmake para detecção de recursos.

(1) é categoricamente não vai acontecer. (2) parece razoável. (3) parece muito trabalho. (4) não vai acontecer porque introduz dependências externas.

Para (2), acredito que o teste é tão fácil quanto:

//  For Microsoft's cl.exe, pivot on _MSC_VER, not __cplusplus.
#if (_MSC_VER >= 1600) || (__cplusplus >= 201103L)
# define MYLIB_CXX11 1
#endif

// Ancient C++ runtime library; unset it because its too much trouble.
// Thanks to Jonathan Wakely for the '__has_include(<forward_list>)'
//     test. See http://stackoverflow.com/q/31655462.
// TODO: test under Xcode 3, where g++ is really g++.
#if defined(__clang__)
#    if !(__has_include(<forward_list>))
#        undef MYLIB_CXX11
#    endif
#endif

Em seguida, volte para a detecção de recursos canonicalizados:

#if MYLIB_CXX11

  // Everyone appears to provide this list
  #define MYLIB_CXX11_UNIQUE_PTR 1
  ...

  // template aliases: MS at VS 2015 (v19.00); GCC at 4.7; Clang at 3.0; and Intel 12.1.
  #if (_MSC_VER >= 1900) || (__INTEL_COMPILER >= 1210)
  #  define MYLIB_CXX11_TEMPLATE_ALIAS 1
  #elif defined(__clang__)
  #  if (__has_feature(cxx_alias_templates))
  #    define MYLIB_CXX11_TEMPLATE_ALIAS 1
  #  endif
  #elif (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
  #  define MYLIB_CXX11_TEMPLATE_ALIAS 1
  #endif // template aliases

#endif // MYLIB_CXX11

PERGUNTAS

Existem outras estratégias para lidar com o C ++ 11 e OS X?

Alguém já tentou a estratégia (3)? Se sim, quanto trabalho foi?

TESTE

Se você tiver acesso ao OS X, tente o seguinte para testar o compilador interno, o padrão, e o libstdc++ do GNU versus libc++ do LLVM. Depois disso, teste com um compilador moderno exportando CXX=/opt/local/bin/clang++ .

$ cat test-clapple.cxx

// c++ -c test-clapple.cxx
// c++ -stdlib=libc++ -c test-clapple.cxx
// c++ -std=c++11 -c test-clapple.cxx
// c++ -std=c++11 -stdlib=libc++ -c test-clapple.cxx

# include <memory>

// Manage auto_ptr warnings and deprecation in C++11
#if (__cplusplus >= 201103L) || (_MSC_VER >= 1900)
  template<typename T>
    using auto_ptr = std::unique_ptr<T>;
#else
    using std::auto_ptr;
#endif // C++11

int main(int argc, char* argv[])
{
    return argc;
}
    
por jww 02.08.2015 / 02:00
fonte

1 resposta

3

Não é MacOSX, é o compilador que você usa nele.

Então, simplesmente atualize seu compilador , talvez construindo de seu código-fonte a recente versão do Clang / LLVM e / ou GCC compilador (es).

(você não precisa da permissão da Apple para compilar e usar um compilador mais novo. Você só precisa ler e seguir as instruções de compilação; em algumas horas, você pode obter a última versão do GCC ou de Clang em execução no seu computador)

Em dezembro de 2015, o GCC atual é GCC 5.3 , e o atual Clang é Clang 3.7 ; e você poderia configurá-los para que o compilador fosse chamado g++-mine ou clang++-mine se você quiser.

    
por 09.12.2015 / 22:06
fonte