Как правильно выставить базовый тип шаблона для использования в качестве типа - PullRequest
1 голос
/ 04 марта 2020

У меня есть некоторый класс строки IMyString, и это может быть либо строка wstring, либо обычная строка. Он имеет два происхождения MyString и MWString. Если шаблонный код хочет принять и то, и другое, ему в настоящее время нужны как аргумент строкового типа, так и аргумент типа char. Я хотел это изменить.

Это мой код:

// 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!");
}

G CC Ошибка, которую я получаю сейчас:

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

Но когда я удаляю имя типа, это тоже ошибка:

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

Как это сделать правильно? Я хочу использовать IMyString::ValueType, как если бы это был вложенный класс / struct / enum.

Я вижу, что это работает, но я бы не стал писать typename везде, где я использую ValueType:

// 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 typename StringType::ValueType* dataToAdd)
{
  StringType string2 = string + dataToAdd;
  // even if the addition worked, it has no effect because the value is not returned
}

Существует ли краткое определение, позволяющее ValueType действовать как реальный тип?

1 Ответ

0 голосов
/ 04 марта 2020

Лучшее, что вы можете сделать, это что-то в этом роде - написать псевдоним помощника, который окутывает презираемое имя пользователя. Живой пример

template<class T>
using char_t = typename T::ValueType;

// 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 char_t<StringType>* dataToAdd)
{
  StringType string2 = string + dataToAdd;
  // even if the addition worked, it has no effect because the value is not returned
}
...