vérifiez si le membre existe en utilisant enable if
Voici ce que j'essaie de faire:
template <typename T> struct Model
{
vector<T> vertices ;
#if T has a .normal member
void transform( Matrix m )
{
each vertex in vertices
{
vertex.pos = m * vertex.pos ;
vertex.normal = m * vertex.normal ;
}
}
#endif
#if T has NO .normal member
void transform( Matrix m )
{
each vertex in vertices
{
vertex.pos = m * vertex.pos ;
}
}
#endif
} ;
J'ai vu exemples de l'aide de enable_if
, mais je ne peux pas comprendre comment appliquer enable_if
à ce problème, ou si elle peut même être appliquée.
26
demandé sur
Community
2012-12-09 15:12:48
3 réponses
Cela est devenu way plus facile avec C++11.
template <typename T> struct Model
{
vector<T> vertices;
void transform( Matrix m )
{
for(auto &&vertex : vertices)
{
vertex.pos = m * vertex.pos;
modifyNormal(vertex, m, special_());
}
}
private:
struct general_ {};
struct special_ : general_ {};
template<typename> struct int_ { typedef int type; };
template<typename Lhs, typename Rhs,
typename int_<decltype(Lhs::normal)>::type = 0>
void modifyNormal(Lhs &&lhs, Rhs &&rhs, special_) {
lhs.normal = rhs * lhs.normal;
}
template<typename Lhs, typename Rhs>
void modifyNormal(Lhs &&lhs, Rhs &&rhs, general_) {
// do nothing
}
};
Choses à noter:
- vous pouvez nommer des membres de données non statiques dans
decltype
etsizeof
sans avoir besoin d'un objet. - vous pouvez appliquer SFINAE étendu. Fondamentalement, toute expression peut être vérifiée et si elle n'est pas valide lorsque les arguments sont substitués, le modèle est ignoré.
26
répondu
Johannes Schaub - litb
2012-12-09 13:51:42
Vous avez besoin d'une fonction meta pour détecter votre membre afin que vous puissiez utiliser enable_if
. L'idiome pour ce faire est appelé Détecteur de membre . C'est un peu délicat, mais ça peut être fait!
7
répondu
ltjax
2012-12-09 11:35:11
Ce n'est pas une réponse à votre cas exact, mais c'est une réponse alternative au titre de la question et au problème en général.
#include <iostream>
#include <vector>
struct Foo {
size_t length() { return 5; }
};
struct Bar {
void length();
};
template <typename R, bool result = std::is_same<decltype(((R*)nullptr)->length()), size_t>::value>
constexpr bool hasLengthHelper(int) {
return result;
}
template <typename R>
constexpr bool hasLengthHelper(...) { return false; }
template <typename R>
constexpr bool hasLength() {
return hasLengthHelper<R>(0);
}
// function is only valid if `.length()` is present, with return type `size_t`
template <typename R>
typename std::enable_if<hasLength<R>(), size_t>::type lengthOf (R r) {
return r.length();
}
int main() {
std::cout <<
hasLength<Foo>() << "; " <<
hasLength<std::vector<int>>() << "; " <<
hasLength<Bar>() << ";" <<
lengthOf(Foo()) <<
std::endl;
// 1; 0; 0; 5
return 0;
}
Pertinents https://ideone.com/utZqjk.
crédits à dyreshark sur le Freenode IRC #C++.
2
répondu
dcousens
2017-03-15 06:01:45