Specialization of a class with a different signature

I am trying to write a class template in which method signatures change depending on the template parameters. My goal is to minimize code duplication. Consider this example: first declaring a class:

// a.hxx #ifndef A_HXX #define A_HXX template<typename T> struct A { void foo(T value) const; void bar() const; }; #include <string> #ifndef short_declaration template<> struct A<std::string> { void foo(const std::string &value) const; void bar() const; }; #else // short_declaration template<> struct A<std::string> { void foo(const std::string &value) const; }; #endif // short_declaration #endif // A_HXX 

Now the class definition:

 // a_impl.hxx #ifndef A_IMPL_HXX #define A_IMPL_HXX #include "a.hxx" #include <iostream> #include <typeinfo> template<typename T> void A<T>::foo(T value) const { std::cout << "A<T=" << typeid(T).name() << ">::foo(" << value << ")" << std::endl; } template<typename T> void A<T>::bar() const { std::cout << "A<T=" << typeid(T).name() << ">::bar()" << std::endl; } void A<std::string>::foo(const std::string &value) const { std::cout << "A<std::string>::foo(" << value << ")" << std::endl; } #ifndef skip_duplicates void A<std::string>::bar() const { std::cout << "A<std::string>::bar()" << std::endl; } #endif // skip_duplicates #endif // A_IMPL_HXX 

And now the test program:

 // test.cxx //#define skip_duplicates //#define short_declaration #include "a_impl.hxx" int main(void) { A<int> obj1; A<std::string> obj2; int value1(1); std::string value2("baz"); obj1.foo(value1); obj1.bar(); obj2.foo(value2); obj2.bar(); return 0; } 

If this compiles, I get the expected output (for my typeid implementation):

 A<T=i>::foo(1) A<T=i>::bar() A<std::string>::foo(baz) A<std::string>::bar() 

But of course I would like to include the skip_duplicates method or even short_declaration in my example. In a more than similar question, ecatmur answered that a full class should be given, so at least the definition of short_declaration will not work.

How do others deal with the problem of creating class templates using methods that can take large objects as arguments?

+4
source share
2 answers

Based on hansmaad's answer and Yakk 's comments, I think the Following is the solution I will go with:

 // a.hxx #ifndef A_HXX #define A_HXX template<typename T, typename U=T> struct Abase { void foo(U value) const; void bar() const; }; template<typename T> struct A : Abase<T> { }; #include <string> template<> struct A<std::string> : Abase<std::string, const std::string &> { }; #endif // A_HXX 

And this implementation:

 // a_impl.hxx #ifndef A_IMPL_HXX #define A_IMPL_HXX #include "a.hxx" #include <iostream> #include <typeinfo> template<typename T, typename U> void Abase<T, U>::foo(U value) const { std::cout << "A<T=" << typeid(T).name() << ",U=" << typeid(U).name() << ">::foo(" << value << "): &value=" << int(&value) << std::endl; } template<typename T, typename U> void Abase<T, U>::bar() const { std::cout << "A<T=" << typeid(T).name() << ",U=" << typeid(U).name() << ">::bar()" << std::endl; } #endif // A_IMPL_HXX 

The test program may remain as is or receive additional lines like these:

 //... std::cout << "&value=" << int(&value1) << std::endl; //... std::cout << "&value=" << int(&value2) << std::endl; //... 

Thank you for your reply and for your suggestions!

0
source

You can extract duplicates in the base class:

 template<typename T> struct Base{ void Bar() { std::cout << "A<T=" << typeid(T).name() << ">::bar()" << std::endl; } protected: ~Base(){} template<typename U> void DoFoo(U value) { std::cout << "A<T=" << typeid(T).name() << ">::foo(" << value << ")" << std::endl; } }; template<typename T> struct A : Base<T> { void Foo(T value) { DoFoo(value); } }; template<> struct A<std::string> : Base<std::string> { void Foo(const std::string& value) { DoFoo(value); } }; 
+2
source

All Articles