代码之家  ›  专栏  ›  技术社区  ›  Werner

模板模板条件编译

  •  0
  • Werner  · 技术社区  · 10 年前

    我不知道我使用的策略是否正确,但我希望使用带有布尔值参数的模板,这样当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();
    
    
    }
    

    我可以申报 fmethod1 fmethod2 方法(将其设置为返回true),从而获得以下结果:

    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
    

    但我想找到一种方法,这样我就不需要为 Caller 如果 Wrapper 不需要,但编译器似乎( gcc )当模板属性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 ?

    2 回复  |  直到 10 年前
        1
  •  1
  •   user2249683 user2249683    10 年前

    您可以考虑奇怪的重复模板模式,并使用静态多态性:

    #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();
    }
    
        2
  •  1
  •   Oktalist    10 年前

    在您的 Wrapper 您可以将呼叫移动到 fmethod1 fmethod2 仅当存在正确的模板参数时,这些函数才被实例化:

        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 限定词,但这与问题无关。