Dedução de modelo e constexpr em tempo de compilação dependente de sinalizadores de compilador e otimização

A pergunta a seguir é condensada a partir de um código muito maior. Portanto, algumas expressões parecem ser um exagero ou desnecessárias, mas são cruciais para o código original.

Considere ter uma estrutura, que contém constantes de tempo de compilação e uma classe simples de contêiner:

template<typename T> struct CONST
{
    static constexpr T ONE()
    {
         return static_cast<T>( 1 );
    }
};

template<typename T> class Container
{
public:
    using value_type = T;
    T value;
};

Agora, com uma função de modelo, que possui uma "especialização" para tipos que oferecem umvalue_type:

template<typename T> void doSomething( const typename T::value_type& rhs )
{}

Agora eu esperaria que isso funcionasse:

template<typename T> class Tester
{
public:
    static constexpr T ONE = CONST<T>::ONE();

    void test()
    {
        doSomething<Container<T>>( ONE );
    }
};

O ponto interessante é que o compilador não reclama da definição deTester<T>::ONE, mas seu uso. Além disso, não reclama, se eu usarCONST<T>::ONE() ou mesmostatic_cast<T>( ONE ) ao invés deONE na chamada de função. No entanto, ambos devem ser conhecidos em tempo de compilação e, portanto, utilizáveis. Portanto, minha primeira pergunta é: o compilador, nos casos em que funciona, faz os cálculos em tempo de compilação?

Eu verifiquei com og++-5, g++-6 e aclang-3.8 compilador usando o-std=c++14 bandeira. Todos reclamam

undefined reference to `Tester<int>::ONE'

embora todos os recursos usados estejam, até onde eu saiba, no padrão e, portanto, devam ser suportados. Curiosamente, a compilação foi bem-sucedida assim que adicionei um sinalizador de otimizaçãoO1, O2 ouO3. Portanto, minha segunda pergunta é: Existe uma estratégia do compilador executando apenas cálculos de tempo de compilação, se os sinalizadores de otimização estiverem ativos? Eu esperava que pelo menos coisas declaradas como constantes em tempo de compilação sejamsempre deduzido!

A última parte da minha pergunta abrange a NVIDIAnvcc compilador (versão 8.0). Como só posso passar-std=c++11 para isso, pode ser que alguns recursos geralmente não sejam cobertos. No entanto, usando um dos compiladores host acima, ele reclama

error: identifier "Tester<int> ::ONE" is undefined in device code

mesmo se um sinalizador de otimização for passado! Obviamente, esse é o mesmo problema acima, mas, embora as perguntas acima sejam mais acadêmicas (porque eu posso simplesmente usar um sinalizador de otimização para se livrar do problema), aqui é realmente um problema (sobre o fato de eu não saber) , o que é feito no momento da compilação quando eu uso as soluções alternativas mencionadas acima - e isso também é mais feio). Então, minha terceira pergunta é: existe uma maneira de usar as otimizações também no código do dispositivo?

O código a seguir é um MWE para host puro e também para o compilador nvcc:

#include <iostream>
#include <cstdlib>

#ifdef __CUDACC__
    #define HD __host__ __device__
#else
    #define HD
#endif


template<typename T> struct CONST
{
    HD static constexpr T ONE()
    {
        return static_cast<T>( 1 );
    }
};


template<typename T> class Container
{
public:
    using value_type = T;
    T value;
};


template<typename T> HD void doSomething( const typename T::value_type& rhs ) {}


template<typename T> class Tester
{
public:
    static constexpr T ONE = CONST<T>::ONE();

    HD void test()
    {
        doSomething<Container<T>>( ONE );
        // doSomething<Container<T>>( static_cast<T>( ONE ) );
        // doSomething<Container<T>>( CONST<T>::ONE() );
    }
};


int main()
{
    using t = int;

    Tester<t> tester;
    tester.test();

    return EXIT_SUCCESS;
}

Desde já, obrigado!

questionAnswers(1)

yourAnswerToTheQuestion