mercredi 4 mars 2020

How to properly expose underlying template type to be used as type

I have some string class IMyString and that can be either wstring or normal string. It has two derivations MyString and MWString. If a templated code wants to accept both, it currently needs both the string type argument and char type argument. I wanted to change that.

This is my code:

// This string doesn't work, it's just an example
template <typename CharType, typename Derived>
class IMyString
{
public:
  // Define value type so that it can ba accessed by other templates (does not work)
  using ValueType = typename CharType;

  const CharType* c_str() const { return rawData; }
  // Does not actually do the adition for brevity, just imagine it instead
  Derived&& operator+(const CharType* moreData) const { return Derived(/*should add my own data here and also copy everything etc*/moreData); }

protected:
  IMyString(const CharType* rawData) : rawData(rawData) {}

  const CharType* rawData = nullptr;
};

// Normal string
class MyString : public IMyString<char, MyString>
{
public:
  MyString(const char* data) : IMyString(data) {}

};

// Wide char string
class MyWString : public IMyString<wchar_t, MyString>
{
public:
  MyWString(const wchar_t* data) : IMyString(data) {}

};

// Method that doesn't really do anything actually
template <typename StringType>
// I want to be able to use the value type directly as type
void DoSomethingWithAnyString(StringType string, const StringType::ValueType* dataToAdd)
{
  StringType string2 = string + dataToAdd;
  // even if the addition worked, it has no effect because the value is not returned
}

int main()
{
  MyString someString("Hello");
  DoSomethingWithAnyString(someString, " world!");
}

GCC error I get now:

UnderlyingTemplateType.cpp:9:30: error: expected nested-name-specifier before 'CharType'
   using ValueType = typename CharType;

But when I remove typename, that's an error too:

UnderlyingTemplateType.cpp:40:56: error: need 'typename' before 'StringType::ValueType' because 'StringType' is a dependent scope
 void DoSomethingWithAnyString(StringType string, const StringType::ValueType* dataToAdd)

How to do this correctly? I want to use IMyString::ValueType as I would if it was a nested class/struct/enum.

Aucun commentaire:

Enregistrer un commentaire