Pergunta

Se eu fizer um membro ponteiro para base, posso convertê-lo em um membro ponteiro-derivado geralmente, mas não quando usado em um modelo como o zumbido abaixo, onde o primeiro argumento do modelo influencia o segundo. Estou lutando contra bugs do compilador ou o padrão realmente exige que isso não funcione?

struct Foo
{
    int x;
};

struct Bar : public Foo
{
};

template<class T, int T::* z>
struct Buzz
{
};

static int Bar::* const workaround = &Foo::x;

int main()
{
    // This works. Downcasting of pointer to members in general is fine.
    int Bar::* y = &Foo::x;

    // But this doesn't, at least in G++ 4.2 or Sun C++ 5.9. Why not?
    // Error: could not convert template argument '&Foo::x' to 'int Bar::*'
    Buzz<Bar, &Foo::x> test;

    // Sun C++ 5.9 accepts this but G++ doesn't because '&' can't appear in
    // a constant expression
    Buzz<Bar, static_cast<int Bar::*>(&Foo::x)> test;

    // Sun C++ 5.9 accepts this as well, but G++ complains "workaround cannot
    // appear in a constant expression"
    Buzz<Bar, workaround> test;

    return 0;
}
Foi útil?

Solução

Simplesmente não é permitido. De acordo com §14.3.2/5:

As conversões a seguir são realizadas em cada expressão usada como um argumento de modelo não do tipo. Se um argumento de modelo não do tipo não puder ser convertido para o tipo de parâmetro de modelo correspondente, o programa será mal formado.
-Para um parâmetro de modelo não do tipo de integral ou tipo de enumeração, são aplicadas promoções integrais (4.5) e conversões integrais (4.7).
-Para um parâmetro de modelo não do tipo de tipo de ponteiro de tipo para objeto, são aplicadas conversões de qualificação (4.4) e a conversão de matriz em ponte (4.2). -Para um parâmetro de modelo não do tipo de tipo de referência de tipo ao objeto, nenhuma conversa se aplica. O tipo referido pela referência pode ser mais qualificado pelo CV do que o tipo (de outra forma idêntico) do argumento do modelo. O parâmetro de modelo está ligado diretamente ao argumento do modelo, que deve ser um LValue.
-Para um parâmetro de modelo não do tipo de tipo de ponteiro de tipo para funcionar, apenas a conversão de função em ponte (4.3) é aplicada. Se o argumento do modelo representar um conjunto de funções sobrecarregadas (ou um ponteiro para esse), a função correspondente será selecionada no conjunto (13.4).
-Para um parâmetro de modelo não do tipo de referência de tipo à função, nenhuma conversões se aplica. Se o argumento do modelo representar um conjunto de funções sobrecarregadas, a função correspondente será selecionada no conjunto (13.4).
-Para um parâmetro de modelo não do tipo de ponteiro de tipo para a função do membro, nenhuma conversões se aplica. Se o argumento do modelo representar um conjunto de funções de membros sobrecarregadas, a função de membro correspondente será selecionada no conjunto (13.4).
Para um parâmetro de modelo não do tipo de ponteiro de tipo para membro de dados, são aplicadas conversões de qualificação (4.4).

Eu enfatizei a conversão em relação ao ponteiro para os membros de dados. Observe que sua conversão (§4.11/2) não está listada. Em C ++ 0x, permanece o mesmo a esse respeito.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top