2015-01-26 3 views
0

올바른 전략을 사용하고 있는지 잘 모르겠지만 bool 값 매개 변수가있는 템플릿을 사용하려고합니다. 따라서 method1과 method2가 false로 설정되어 있으면 호출 할 필요가 없습니다. fmethod1 또는 fmethod2. 나는 그 일을 동적 테이블을 사용할 수 있지만 난 그냥 템플릿을 사용하여이 작업을 수행 할 수 있다는 것을 발견하고, 나는 다음과 같이 구문 사용을 훈련했다 :템플릿 템플릿 조건부 컴파일

#include<iostream> 

template<bool method1, bool method2> 
class Caller { 

    public: 

    Caller(const float prop1, const float prop2):prop1(prop1),prop2(prop2){;} 

    float prop1; 
    float prop2; 

    bool fmethod1(){ 
     return prop1; 
    } 

    bool fmethod2(){ 
     return prop2; 
    } 

    void mainMethod(){ 
     std::cout << "Caller<" << method1 << "," << method2 << ">(" << prop1 << ")" << std::endl; 
     std::cout << "fmethod1()" << fmethod1() << std::endl; 
     std::cout << "fmethod2()" << fmethod2() << std::endl; 
    }; 

}; 

template<> 
class Caller<true,false> { 

    public: 
    Caller(const float prop2):prop2(prop2){;} 
    float prop2; 

    // I can declare here to return true, but this 
    // shouldn't be called in Wrapper, since Wrapper method1 is set 
    // to false (the first "or" on wrapper should be set to true and 
    // compiler shouldn't need this method.) 
    bool fmethod1(); 

    bool fmethod2(){ 
     return prop2; 
    } 

    void mainMethod(){ 
     std::cout << "Caller<true,false>" << std::endl; 
     std::cout << "fmethod2()" << fmethod2() << std::endl; 
    }; 

}; 

template<> 
class Caller<false,true> { 

    public: 
    Caller(const float prop1):prop1(prop1){;} 
    float prop1; 

    bool fmethod1(){ 
     return prop1; 
    } 
    bool fmethod2(); // Same here 

    void mainMethod(){ 
     std::cout << "Caller<false,true>" << std::endl; 
     std::cout << "fmethod1()" << fmethod1() << std::endl; 
    }; 

}; 

template<> 
class Caller<false,false> { 

    public: 
    bool fmethod1(){ 
     return true; 
    } 

    bool fmethod2(){ 
     return true; 
    } 

    void mainMethod(){ 
     std::cout << "Caller<false,false>" << std::endl; 
     std::cout << "fmethod1()" << fmethod1() << std::endl; 
     std::cout << "fmethod2()" << fmethod2() << std::endl; 
    }; 

}; 

template<template<bool, bool> class holded_t,bool method1, bool method2> 
class Wrapper{ 

    public: 
    holded_t<method1,method2> holded; 

    Wrapper():holded(holded_t<method1,method2>()){;} 
    Wrapper(float prop1):holded(holded_t<method1,method2>(prop1)){;} 
    Wrapper(float prop1, float prop2):holded(holded_t<method1,method2>(prop1,prop2)){;} 

    void mainMethod(){ 
     if(!method1 || holded.fmethod1()){ 
     if(!method2 || holded.fmethod2()){ 
      holded.mainMethod(); 
     } else { 
      std::cout << "holded method2 is false" << std::endl; 
     } 
     } else { 
     std::cout << "holded method1 is false" << std::endl; 
     } 
    } 
}; 


int main(){ 

    Wrapper<Caller,false,false> holder_ex_false_false; 
    holder_ex_false_false.mainMethod(); 
    Wrapper<Caller,false,true> holder_ex_false_true(0); 
    holder_ex_false_true.mainMethod(); 
    Wrapper<Caller,true,false> holder_ex_true_false(0); 
    holder_ex_true_false.mainMethod(); 
    Wrapper<Caller,true,true> holder_ex_true_true(0,0); 
    holder_ex_true_true.mainMethod(); 
    Wrapper<Caller,true,true> holder_ex_true_true1(1,0); 
    holder_ex_true_true1.mainMethod(); 
    Wrapper<Caller,true,true> holder_ex_true_true2(0,1); 
    holder_ex_true_true2.mainMethod(); 
    Wrapper<Caller,true,true> holder_ex_true_true3(1,1); 
    holder_ex_true_true3.mainMethod(); 


} 

나는 설정 (전문 분야에 fmethod1fmethod2 방법을 선언 할 수 있습니다 Wrapper이 필요하지 않는 경우 나는 Caller에 대한 방법 항목이나 방법 2를 구현해야하지 않도록 할 수있는 방법을

Caller<false,false> 
fmethod1()1 
fmethod2()1 
Caller<false,true> 
fmethod1()0 
fmethod2()1 
Caller<true,false> 
fmethod1()1 
fmethod2()0 
holded method1 is false 
holded method2 is false 
holded method1 is false 
Caller<1,1>(1) 
fmethod1()1 
fmethod2()1 

하지만 내가 원하는 : 그것은 다음과 같은 결과를 얻을 수 있도록)가 true를 반환 그것,하지만 그 컴파일러 (gcc) 볼 수없는 것 템플리트 property method1이 false 인 경우 fmethod1이 필요하지 않습니다. 나는 같은 것 대신에 일반 상속 virtual 방법에 대한 이러한 접근 방식에 어떤 혜택을받을 경우

내 첫 번째 질문은 다음과 같습니다

class Caller{ 
    public: 
    virtual bool fmethod1(){return true;} 
    virtual bool fmethod2(){return true;} 
} 

class CallerMethod1Active: public Caller{ 
    public: 
    float prop1; 
    bool fmethod1(){return prop1;} 
    bool fmethod2(){return true;} 
} 
… 

그리고 두 번째, 나는이 생각없이 구현할 수 방법에 대한 아이디어 Caller fmethod1을 구현해야합니까?

당신은 호기심 반복 템플릿 패턴을 고려하고 정적 다형성 사용할 수
+1

사이드 노트 (나는 지금 당장 귀하의 문제를 풀 시간이 없습니다.) : 부울 템플릿 인수 대신, 매개 변수가 무엇을하는지 표현하는 데 도움이되는 열거 형을 사용할 수도 있습니다. 'Caller '은 "Caller "보다 직관적입니다. – stefan

+0

실제로 @stefan, 열거 형을 사용하려고 생각했지만 예제를 더 단순하게 만들기 위해 부울을 사용했습니다. 어쨌든 팁 주셔서 감사합니다! – Werner

+1

'Wrapper' **는'holded.fmethod1()'에서 **'fmethod1()'이 필요합니다. – Jarod42

답변

1

: 당신의 Wrapper 올바른 템플릿 인수가있는 경우에만 인스턴스화 별도의 도우미 기능에 fmethod1fmethod2로 통화를 이동할 수 있습니다에서

#include <iostream> 

template<typename Derived> 
class BasicCaller 
{ 
    protected: 
    BasicCaller() {} 

    public: 
    void method() { 
     static_cast<Derived*>(this)->method1(); 
     static_cast<Derived*>(this)->method2(); 
    } 

    protected: 
    bool method1() { return false; } 
    bool method2() { return false; } 
}; 

class CallNone : public BasicCaller<CallNone> {}; 

class CallFirst : public BasicCaller<CallFirst> 
{ 
    friend class BasicCaller<CallFirst>; 

    protected: 
    bool method1() { 
     std::cout << "First\n"; 
     return true; 
    } 
}; 

class CallSecond : public BasicCaller<CallSecond> 
{ 
    friend class BasicCaller<CallSecond>; 

    protected: 
    bool method2() { 
     std::cout << "Second\n"; 
     return true; 
    } 
}; 

class CallBoth : public BasicCaller<CallBoth> 
{ 
    friend class BasicCaller<CallBoth>; 

    protected: 
    bool method1() { 
     std::cout << "Both First\n"; 
     return true; 
    } 

    bool method2() { 
     std::cout << "Both Second\n"; 
     return true; 
    } 

}; 


int main() 
{ 
    std::cout << "CallNone\n"; 
    CallNone a; 
    a.method(); 
    std::cout << "CallFirst\n"; 
    CallFirst b; 
    b.method(); 
    std::cout << "CallSecond\n"; 
    CallSecond c; 
    c.method(); 
    std::cout << "CallBoth\n"; 
    CallBoth d; 
    d.method(); 
} 
+0

이 호출은 아마도 BasicCaller의 생성자에 있어서는 안됩니다 ... –

+0

@ T.C. 당신 말이 맞아요 (나의 게으름) –

1

을 이들이라고, 멤버 함수는 경우에만 인스턴스화 클래스 템플릿이기 때문에

void mainMethod(){ 
     if(testmethod1(std::integral_constant<bool, method1>())){ 
     if(testmethod2(std::integral_constant<bool, method2>())){ 
      holded.mainMethod(); 
     } else { 
      std::cout << "holded method2 is false" << std::endl; 
     } 
     } else { 
     std::cout << "holded method1 is false" << std::endl; 
     } 
    } 
    bool testmethod1(std::true_type) { return holded.fmethod1(); } 
    bool testmethod1(std::false_type) { return false; } 
    bool testmethod2(std::true_type) { return holded.fmethod2(); } 
    bool testmethod2(std::false_type) { return false; } 

을, 과부하 해상도는 시도하지 않습니다 : 제시 인수와 일치하지 않는 함수를 호출합니다.

함수에 const 한정자가 누락되었지만 질문과 관련이 없습니다.