Question

J'écris un code de point simple en essayant Visual Studio 10 (version bêta 2), et j'ai frappé ce code là où je m'attendrais à ce que SFINAE prenne effet, mais il ne semble pas que:

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);
}

Ceci donne error C2512: 'point<T>::point' : no appropriate default constructor available

Etant donné qu’il s’agit d’une version bêta, j’ai effectué une vérification de cohérence rapide avec le compilateur de comeau en ligne, qui concorde avec une erreur identique. Il semble donc que ce comportement soit correct, mais je ne vois pas pourquoi.

Dans ce cas, certaines solutions de contournement consistent simplement à insérer le decltype(T() / U()) en-ligne, à donner à la classe de points un constructeur par défaut ou à utiliser decltype sur l'expression de résultat complète, mais j'ai eu cette erreur en essayant de simplifier une erreur que je rencontrais avec une version d’op_div ne nécessitant pas de constructeur par défaut *, je préfère donc améliorer ma compréhension de C ++ plutôt que de simplement faire ce qui fonctionne.

Merci!

*: l'original:

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

Ce qui donne 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', ainsi que pour la point<T> / point<U> surcharge.

Était-ce utile?

La solution

Pas sûr à 100%. Il semble que le compilateur ait besoin d’instancier les deux surcharges pour déterminer lequel est le meilleur. Cependant, si vous essayez d’instancier l’autre op_div avec T = int et U = point<float>, cela entraîne une erreur qui n’est pas couverte par SFINAE (l’erreur op_div n'a pas de type dans ce cas, mais ce type ne peut pas être déterminé).

Vous pouvez essayer de désactiver la seconde surcharge si le second type est un point (boost::disable_if).

De plus, ce qui semble fonctionner est la déclaration de type de retour reportée (suppression de la structure op_div, mais en fonction des fonctionnalités C ++ 0x prises en charge par votre compilateur):

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};
}

Autres conseils

Je dirais que votre erreur est ici:

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

Modifiez votre définition de structure en ceci:

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

Si vous souhaitez utiliser un type générique T, vous devez le spécifier dans la définition.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top