Question

I'm just starting with C++, and I'm trying to create a class that extends the functionalities of basic_string < unsigned char > to let it accept chars as arguments for the constructors too, and they'd be handled by casting them and calling the base constructors for basic_string.

I've been told to use template specialization for that, but I've been struggling with it, so I've created a simple extract of the current problem: how template specialization works:

template<typename T> class TestClass{
  public:
    // Sample constructor
    TestClass(const char* name){
      std::cout << "Created class " << name << std::endl;
    }
};

// Doesn't add any functionalities, just used as an example
template<> class TestClass<int>{};

As expected, if I use the following:

  TestClass<char> test = TestClass<char>("Test");

The file compiles, and the output is correct.

But if I use the following:

  TestClass<int> specializedTest = TestClass<int>("Specialized Test");

The file doesn't compile, throwing the following error:

test.cpp: In function ‘int main()’:
test.cpp:50:69: error: no matching function for call to ‘TestClass<int>::TestClass(const char [17])’
test.cpp:50:69: note: candidates are:
test.cpp:47:18: note: TestClass<int>::TestClass()
test.cpp:47:18: note:   candidate expects 0 arguments, 1 provided
test.cpp:47:18: note: TestClass<int>::TestClass(const TestClass<int>&)
test.cpp:47:18: note:   no known conversion for argument 1 from ‘const char [17]’ to ‘const TestClass<int>&’

Question 1: Shouldn't the specialized class inherit the TestClass's members and functions? Because if it doesn't, it looks to me that I'm just creating a class and "masking" it as the base class. i.e. (in pseudocode)

class SpecializedTestClass{/* Add class code here */};
typedef SpecializedTestClass TestClass<int>;

If not, why not? It makes sense for me that, if you're specializing a class, all classes members/functions should be kept unless they are specialized.

Maybe I'm just mixing template with class inheritance.

Question 2: Is this the best approach to my problem? (Combine the functionalities of basic_string< unsigned char > and basic_string< char > so that the data is stored as unsigned char, but can be assigned from char using typecasts.)

Was it helpful?

Solution

No. When you (explicitly or partially) specialize a class, your specialization is an entirely new template. The only thing it shares with the existing template is its name.

As to why, we can only guess. Two obvious reasons would be that it's fairly difficult (to the point that most compilers didn't implement the current partial specialization spec correctly for years after the standard was written) and that it's probably open to question (at best) whether it's desirable.

As far as this being the best approach: I doubt it, but I don't have a lot better suggestion to give either. Getting string/basic_string to deal nicely with unsigned char has been a problem almost since it was invented, and I haven't seen a way to deal with it yet that produces particularly good results.

OTHER TIPS

Question 1: Shouldn't the specialized class inherit the TestClass's members and functions?

It doesn't, it is a completely unrelated type. This is intentional, consider std::vector<T> and std::vector<bool>, the member are completely different. Specialization is not extending the type, but rather providing a different type for a specific need. There is no base class in an specialization.

Question 2: Is this the best approach to my problem?

I am not sure what the real problem to solve is. There is already an implicit conversion from char to unsigned char, so normal chars should be accepted in the interface… right? If what you mean is passing const char*, (i.e. pointers, not values), then you can provide that externally as a helper function:

basic_string<unsigned char> create(const char* s) {
   return basic_string<unsigned char>(reinterpret_cast<unsigned char*>(s));
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top