C++ specialization of template function inside template class

后端 未结 6 752
暗喜
暗喜 2020-12-05 00:32

What is the C++ syntax for specializing a template function that\'s inside a template class? For example, consider that I have the following two classes and their usage. I

6条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-05 00:48

    So, I'm taking a different approach to answering your question. I'm going to start from something that sort of does what you want, and works. And then maybe we can figure out how to permute it into something closer to what you really want:

    #include 
    #include 
    
    int getIntThing(const ::std::string ¶m);
    
    template 
    returnT getThingFree(const ::std::string ¶m);
    
    template <>
    int getThingFree(const ::std::string ¶m)
    {
       return getIntThing(param);
    }
    
    // More specialized definitions of getAThing() for other types/classes
    // go here...
    
    template  class X {
    public:
       template returnT getAThing(std::string param);
       static std::string getName();
    private:
       c1 theData;
    };
    
    // This works ok...
    template  std::string X::getName() {
       return c1::getName();
    }
    
    // This also works, but it would be nice if I could explicitly specialize
    // this instead of having to explicitly specialize getThingFree.
    template 
    template 
    RT X::getAThing(std::string param) {
       // Some function that crunches on param and returns an RT.
       // Gosh, wouldn't it be nice if I didn't have to redirect through
       // this free function?
       return getThingFree(param);
    }
    
    class Y {
    public:
       static std::string getName() { return "Y"; }
    };
    
    int main(int argc, char* argv[])
    {
       using ::std::cout;
       X tester;
       int anIntThing = tester.getAThing(std::string("param"));
       cout << "Name: " <<  tester.getName() << '\n';
       cout << "An int thing: " << anIntThing << '\n';
    }
    

    Here is another idea that sort of works, and isn't exactly what you want, but is closer. I think you've thought of it yourself. It's also rather ugly in the way it uses type deduction.

    #include 
    #include 
    
    template  class X;
    
    int getIntThing(const ::std::string ¶m)
    {
       return param.size();
    }
    
    // You can partially specialize this, but only for the class, or the
    // class and return type. You cannot partially specialize this for
    // just the return type. OTOH, specializations will be able to access
    // private or protected members of X as this class is declared a
    // friend.
    template 
    class friendlyGetThing {
     public:
       template 
       static return_t getThing(X &xthis, const ::std::string ¶m,
                                return_t *);
    };
    
    // This can be partially specialized on either class, return type, or
    // both, but it cannot be declared a friend, so will have no access to
    // private or protected members of X.
    template 
    class getThingFunctor {
     public:
       typedef return_t r_t;
    
       return_t operator()(X &xthis, const ::std::string ¶m) {
          return_t *fred = 0;
          return friendlyGetThing::getThing(xthis, param, fred);
       }
    };
    
    template  class X {
    public:
       friend class friendlyGetThing;
    
       template returnT getAThing(std::string param) {
          return getThingFunctor()(*this, param);
       }
       static std::string getName();
    private:
       c1 theData;
    };
    
    // This works ok...
    template  std::string X::getName() {
       return c1::getName();
    }
    
    class Y {
    public:
       static std::string getName() { return "Y"; }
    };
    
    template 
    class getThingFunctor {
     public:
       int operator()(X &xthis, const ::std::string ¶m) {
          return getIntThing(param);
       }
    };
    
    // More specialized definitions of getAThingFunctor for other types/classes
    // go here...
    
    int main(int argc, char* argv[])
    {
       using ::std::cout;
       X tester;
       int anIntThing = tester.getAThing(std::string("param"));
       cout << "Name: " <<  tester.getName() << '\n';
       cout << "An int thing: " << anIntThing << '\n';
    }
    

    I would recommend declaring getThingFunctor and friendlyGetThing in a semi-private utility namespace.

提交回复
热议问题