2012-12-09 21 views
6

मैं here की तरह कोड लिखने की कोशिश कर रहा हूँ, लेकिन सी ++ 11 सुविधाओं का उपयोग कर, बूस्ट के बिना।सशर्त संकलन करने के लिए आप प्रकार के लक्षणों का उपयोग कैसे करते हैं?

this example से काम करते हुए, मैंने response_trait को परिभाषित करने की कोशिश की, और विशेषता के परिणाम पर बेस सशर्त संकलन। मै इसे काम मे कैसे ले सकता हूँ?

#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

क्या आप अपना प्रश्न स्वयं निहित कर सकते हैं और वर्णन कर सकते हैं कि आप क्या हासिल करने की कोशिश कर रहे हैं? –

+1

यह स्वयं निहित है। '# यदि' '' '' 'असामान्य 'सदस्य है, तो' प्रतिक्रिया_trait' 'has_normal' सत्य होना चाहिए, और सही संकलन पथ चुना जाना चाहिए। – bobobobo

+0

जब तक मैंने टाइप गुणों को पूरी तरह गलत समझा नहीं है। जुड़ा हुआ प्रश्न मेरा शुरुआती बिंदु था, लेकिन मुझे नहीं पता कि मैंने इसे गलत तरीके से लिया है या नहीं। – bobobobo

उत्तर

15

आप कुछ इस तरह की कोशिश कर सकते:

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

आप बस अपनी विशेषता थोड़ा संशोधित करने की आवश्यकता: अपने कोड में डाल दिया जा सकता है अगर

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

सादा टेम्पलेट विशेषज्ञता के लिए कोई फायदा है? – tauran

+1

@ टॉरन: यह * सादा टेम्पलेट विशेषज्ञता है, है ना? क्या मैं कुछ भूल रहा हूँ? या आप अधिभारित कार्यों का जिक्र कर रहे हैं? फ़ंक्शन टेम्पलेट्स को विशेषज्ञता बहुत पसंद नहीं है ... –

+0

अच्छा उत्तर आदमी। जुड़े प्रश्न में यह गुम है। – bobobobo

1

यहाँ एक वैकल्पिक समाधान है आपके डिज़ाइन को बोझिल बनाने के बिना फ़ंक्शंस (उदाहरण के लिए जब आपको अपनी ऑब्जेक्ट के कई सदस्य चरों तक पहुंच की आवश्यकता होती है)। बेशक कभी-कभी पूरे वर्ग को विशेषज्ञता देने के लिए यह पसंद है।

#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

यह बहुत चालाक है। मैंने सदस्य कार्यों के बजाय वैश्विक कार्यों को बनाने के बारे में नहीं सोचा था। शायद यही कारण है कि एसटीएल के कार्यों में वैश्विक कार्य ('std :: find', आदि) – bobobobo

+2

यह इस तरह से पता चला है कि यह थोड़ा अधिक बोझिल है, यह प्रकार के लक्षणों का उपयोग करने से अधिक प्रकार के टेम्पलेट विशेषज्ञता को प्रोत्साहित करेगा। इस बात पर विचार करें कि क्या आपके पास कुछ और चरम प्रारूप हैं, 'VertexNC' (सामान्य, रंग के साथ vertex),' VertexNTC' (सामान्य, texcoord, रंग के साथ vertex)। प्रकार के लक्षणों में 'hasNormal' ध्वज को चालू या बंद करने के बजाय, आपको टेम्पलेट को _every_ 'Vertex' प्रकार में सामान्य के साथ विशेषज्ञता देना होगा। – bobobobo

+0

यह स्थिति पर निर्भर करता है। इस मामले में मैं भी अन्य समाधान उठाऊंगा :) – tauran