32

これが私がやろうとしていることです:

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

の使用を見たことがありますが、この問題に適用する方法、または適用できるかどうかさえenable_ifわかりません。enable_if

4

6 に答える 6

32

これは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
    }
};

注意事項:

  • オブジェクトを必要とせずdecltypeに、非静的データ メンバーに名前を付けることができます。sizeof
  • 拡張 SFINAE を適用できます。基本的に任意の式をチェックでき、引数を代入したときに有効でない場合、テンプレートは無視されます。
于 2012-12-09T12:51:21.837 に答える
8

を使用できるように、メンバーを検出するためのメタ関数が必要ですenable_if。これを行う慣用句は、Member Detectorと呼ばれます。少し難しいですが、できます!

于 2012-12-09T11:35:11.310 に答える
1

少し遅れていることは承知していますが...

typedef int Matrix;

struct NormalVertex {
    int pos;
    int normal;
};

struct Vertex {
    int pos;
};

template <typename T> struct Model
{
    typedef int No;
    typedef char Yes;

    template<typename U> static decltype (declval<U>().normal, Yes()) has_normal(U a);
    static No has_normal(...);

    vector<T> vertices ;

    template <typename U = T>
    typename enable_if<sizeof(has_normal(declval<U>())) == sizeof(Yes), void>::type
    transform( Matrix m )
    {
        std::cout << "has .normal" << std::endl;
        for (auto vertex : vertices)
        {
          vertex.pos = m * vertex.pos ;
          vertex.normal = m * vertex.normal ;
        }
    }

    template <typename U = T>
    typename enable_if<sizeof(has_normal(declval<U>())) == sizeof(No), void>::type
    transform( Matrix m )
    {
        std::cout << "has no .normal" << std::endl;
        for (auto vertex : vertices)
        {
          vertex.pos = m * vertex.pos ;
        }
    }
} ;

int main()
{
    Matrix matrix;
    Model <NormalVertex> normal_model;

    Vertex simple_vertex;
    Model <Vertex> simple_model;

    simple_model.transform(matrix);
    normal_model.transform(matrix);

    return 0;
}
于 2019-11-05T06:14:00.160 に答える