O problema do idioma estranho é o CWG 1581 :
A cláusula 15 [especial] é perfeitamente clara que funções especiais de membro são definidas implicitamente apenas quando são usadas por odr. Isso cria um problema para expressões constantes em contextos não avaliados:
struct duration {
constexpr duration() {}
constexpr operator int() const { return 0; }
};
// duration d = duration(); // #1
int n = sizeof(short{duration(duration())});
O problema aqui é que não podemos definir implicitamente constexpr duration::duration(duration&&)
neste programa; portanto, a expressão na lista de inicializadores não é uma expressão constante (porque invoca uma função constexpr que não foi definida); portanto, o inicializador entre chaves contém uma conversão restrita , então o programa está mal formado.
Se descomentarmos a linha 1, o construtor de movimentação é implicitamente definido e o programa é válido. Essa ação assustadora à distância é extremamente infeliz. As implementações divergem nesse ponto.
Você pode ler o restante da descrição do problema.
Uma resolução para esse problema foi adotada no P0859 em Albuquerque em 2017 (após o envio do C ++ 17). Esse problema foi um bloqueador para ambos poderem ter um constexpr std::swap
(resolvido em P0879 ) e um constexpr std::invoke
(resolvido em P1065 , que também possui exemplos de CWG1581), ambos para C ++ 20.
O exemplo mais simples de entender aqui, na minha opinião, é o código do relatório de bug do LLVM apontado na P1065:
template<typename T>
int f(T x)
{
return x.get();
}
template<typename T>
constexpr int g(T x)
{
return x.get();
}
int main() {
// O.K. The body of `f' is not required.
decltype(f(0)) a;
// Seems to instantiate the body of `g'
// and results in an error.
decltype(g(0)) b;
return 0;
}
CWG1581 é sobre quando as funções de membro constexpr são definidas e a resolução garante que elas sejam definidas apenas quando usadas. Após P0859, o acima está bem formado (o tipo de b
é int
).
Desde std::swap
e std::invoke
ambos têm de contar com a verificação de funções membro (movimento construção / atribuição no primeiro e o operador de chamada / chamadas substitutos no último), ambos dependia da resolução desta questão.