Pergunta

Estou a escrever algum código simples ponto ao tentar sair Visual Studio 10 (Beta 2), e já atingiu este código onde eu esperaria SFINAE para chutar, mas não parece:

template<typename T>
struct point {
    T x, y;
    point(T x, T y) : x(x), y(y) {}
};

template<typename T, typename U>
struct op_div {
    typedef decltype(T() / U()) type;
};

template<typename T, typename U>
point<typename op_div<T, U>::type>
operator/(point<T> const& l, point<U> const& r) {
    return point<typename op_div<T, U>::type>(l.x / r.x, l.y / r.y);
}

template<typename T, typename U>
point<typename op_div<T, U>::type>
operator/(point<T> const& l, U const& r) {
    return point<typename op_div<T, U>::type>(l.x / r, l.y / r);
}

int main() {
    point<int>(0, 1) / point<float>(2, 3);
}

Isto dá error C2512: 'point<T>::point' : no appropriate default constructor available

Dado que é um beta, eu fiz uma verificação de sanidade rápida com o compilador comeau online, e concorda com um erro idêntico, então parece que este comportamento é correto, mas eu não posso ver o porquê.

Neste caso, algumas soluções são simplesmente em linha o decltype(T() / U()), para dar a classe de ponto de um construtor padrão, ou para uso decltype na expressão resultado completo, mas eu tenho esse erro ao tentar simplificar um erro que eu estava ficando com um versão do op_div que não exigem um construtor padrão *, então eu preferir corrigir o meu entendimento do C ++ em vez de apenas fazer o que funciona.

Obrigado!


*: o original:

template<typename T, typename U>
struct op_div {
    static T t(); static U u();
    typedef decltype(t() / u()) type;
};

O que dá error C2784: 'point<op_div<T,U>::type> operator /(const point<T> &,const U &)' : could not deduce template argument for 'const point<T> &' from 'int', e também para a sobrecarga point<T> / point<U>.

Foi útil?

Solução

Não 100% de certeza. Parece que as necessidades do compilador para instanciar sobrecargas para determinar o que é melhor, mas ao tentar instanciar o outro op_div com T = int e U = point<float>, isso leva a um erro que não é coberto pelo SFINAE (o erro não é que op_div não têm o tipo neste caso, mas esse tipo não pode ser determinada).

Você poderia tentar desativar o segundo sobrecarga se o segundo tipo é um ponto (boost::disable_if).

Além disso, o que parece funcionar é adiada declaração tipo de retorno (acabando com a estrutura op_div, mas dependendo de qual C ++ 0x recursos são suportados pelo seu compilador):

template<typename T, typename U>
auto
operator/(point<T> const& l, point<U> const& r) -> point<decltype(l.x / r.x)> {
    return {l.x / r.x, l.y / r.y};
}

template<typename T, typename U>
auto
operator/(point<T> const& l, U const& r) -> point<decltype(l.x / r)> {
    return {l.x / r, l.y / r};
}

Outras dicas

Eu diria que o seu erro está aqui:

template<typename T>
struct point {
    T x, y;
    point(T x, T y) : x(x), y(y) {}
};

Alterar a sua definição struct a esta:

template<typename T>
struct point<T> {
    T x, y;
    point(T x, T y) : x(x), y(y) {}
};

Se você quiser usar um tipo genérico T, você precisa especificá-lo na definição.

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