2012-12-09 18 views
6

Próbuję napisać kod taki jak here, ale używając funkcji C++ 11, bez zwiększenia.Jak używać typów znaków do kompilacji warunkowej?

Praca z this example, próbowałem zdefiniować response_trait i kompilację warunkową Basee na wynik cechy. Jak mogę to sprawić?

#include <vector> 
using namespace std ; 

struct Vector{ float x,y,z ; } ; 
struct Vertex { Vector pos ; } ; 
struct VertexN { Vector pos, normal ; } ; 
struct Matrix {} ; 

template <typename T> 
struct response_trait { 
    static bool const has_normal = false; 
} ; 

template <> 
struct response_trait<VertexN> { 
    static bool const has_normal = true; 
} ; 

template <typename T> 
struct Model 
{ 
    vector<T> verts ; 

    void transform(Matrix m) 
    { 
    for(int i = 0 ; i < verts.size() ; i++) 
    { 
     #if response_trait<T>::has_normal==true 
     puts("Has normal") ; 
     // will choke compiler if T doesn't have .normal member 
     printf("normal = %f %f %f\n", verts[i].normal.x, verts[i].normal.y, verts[i].normal.z) ; 
     #else 
     puts("Doesn't have normal") ; 
     printf("pos = %f %f %f\n", verts[i].pos.x, verts[i].pos.y, verts[i].pos.z) ; 
     #endif 
    } 
    } 

} ; 

int main() 
{ 
    Matrix m ; 
    Model<Vertex> model ; 
    model.verts.push_back(Vertex()) ; 
    model.transform(m) ; 

    Model<VertexN> modelNormal ; 
    modelNormal.verts.push_back(VertexN()) ; 
    modelNormal.transform(m) ; 
} 
+0

Czy możesz zadać pytanie zamknięte i opisać, co chcesz osiągnąć? –

+1

Jest samodzielny. '# if'' T' ma element '.normal', właściwość' response_trait' 'has_normal' powinna być prawdziwa i należy wybrać poprawną ścieżkę kompilacji. – bobobobo

+0

Chyba że zupełnie źle zrozumiałem cechy typu. Połączone pytanie było moim punktem wyjścia, ale nie mam pojęcia, czy podjąłem to niewłaściwie. – bobobobo

Odpowiedz

15

Można spróbować czegoś takiego:

void transform_impl(Matrix const & m, std::true_type const &) 
{ 
    // has normal 
} 

void transform_impl(Matrix const & m, std::false_type const &) 
{ 
    // doesn't have normal 
} 

template <typename T> 
void transform(Matrix const & m) 
{ 
    transform_impl(m, response_trait<T>()); 
} 

wystarczy zmodyfikować cecha trochę:

#include <type_traits> 
template <typename> struct response_trait : std::false_type { }; 
template <> struct response_trait<VertexN> : std::true_type { }; 
+0

Czy istnieje korzyść dla specjalizacji szablonów? – tauran

+1

@tauran: To jest * zwykła specjalizacja szablonowa, prawda? Czy czegoś brakuje? Czy odnosisz się do przeciążonych funkcji? Szablony funkcji bardzo nie lubią specjalizacji ... –

+0

Niezły pomysł. W połączonym pytaniu brakuje tego. – bobobobo

1

Oto alternatywne rozwiązanie, jeśli Twój kod może być wprowadzony do funkcje nie powodują, że Twój projekt jest uciążliwy (np. gdy potrzebujesz dostępu do wielu zmiennych składowych swojego obiektu). Oczywiście czasami preferuje się specjalizację całej klasy.

#include <vector> 
#include <stdio.h> 

using namespace std ; 

struct Vector{ float x,y,z ; } ; 
struct Vertex { Vector pos ; } ; 
struct VertexN { Vector pos, normal ; } ; 
struct Matrix {} ; 

template <typename T> 
void printVertex(T vert) 
{ 
     printf("Doesn't have normal") ; 
     printf("pos = %f %f %f\n", vert.pos.x, vert.pos.y, vert.pos.z) ; 
} 

template <> 
void printVertex(VertexN vert) 
{ 
     printf("Has normal") ; 
     printf("normal = %f %f %f\n", vert.normal.x, vert.normal.y, vert.normal.z) ; 
} 

template <typename T> 
struct Model 
{ 
    vector<T> verts ; 

    void transform(Matrix m) 
    { 
    for(int i = 0 ; i < verts.size() ; i++) 
    { 
     printVertex(verts[i]); 
    } 
    } 
} ; 

int main() 
{ 
    Matrix m ; 
    Model<Vertex> model ; 
    model.verts.push_back(Vertex()) ; 
    model.transform(m) ; 

    Model<VertexN> modelNormal ; 
    modelNormal.verts.push_back(VertexN()) ; 
    modelNormal.transform(m) ; 
} 
+0

To jest bardzo sprytne. Nie myślałem o tworzeniu globalnych funkcji zamiast funkcji członkowskich. Być może dlatego STL ma swoje funkcje jako funkcje globalne ('std :: find', itp.) – bobobobo

+2

Okazuje się, że w ten sposób jest nieco bardziej uciążliwy, będzie zachęcać do specjalizacji szablonów więcej typów niż przy użyciu cech typu. Zastanów się, czy masz więcej formatów wierzchołków, 'VertexNC' (vertex z normalnym, kolor),' VertexNTC' (vertex z normalnym, texcoord, kolor). Musisz szablon wyspecyfikować _every_ 'Vertex' z normalnym w nim, zamiast ustawiać flagę' hasNormal' na lub wyłącz w cechach typu. – bobobobo

+0

To zależy od sytuacji. W tym przypadku wybrałbym też inne rozwiązanie :) – tauran

Powiązane problemy