C++ 如何正确公开要用作类型的基础模板类型

C++ 如何正确公开要用作类型的基础模板类型,c++,c++11,templates,using,C++,C++11,Templates,Using,我有一些字符串类IMyString,可以是wstring或普通字符串。它有两个派生词MyString和MWString。如果模板化代码希望同时接受这两个参数,则当前需要字符串类型参数和字符类型参数。我想改变这一点 这是我的代码: // This string doesn't work, it's just an example template <typename CharType, typename Derived> class IMyString { public: // D

我有一些字符串类
IMyString
,可以是wstring或普通字符串。它有两个派生词
MyString
MWString
。如果模板化代码希望同时接受这两个参数,则当前需要字符串类型参数和字符类型参数。我想改变这一点

这是我的代码:

// 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!");
}
但当我删除typename时,这也是一个错误:

UnderlyingTemplateType.cpp:40:56: error: need 'typename' before 'StringType::ValueType' because 'StringType' is a dependent scope
 void DoSomethingWithAnyString(StringType string, const StringType::ValueType* dataToAdd)
如何正确地做到这一点?我想像使用嵌套类/struct/enum一样使用
imysting::ValueType

我可以看出这是可行的,但我不想在使用
ValueType
的任何地方都写
typename

// 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
}
//实际上什么都不做的方法
模板
//我希望能够将值类型直接用作类型
void DoSomethingWithAnyString(StringType字符串,常量类型名称StringType::ValueType*dataToAdd)
{
StringType string2=字符串+数据添加;
//即使加法有效,也没有效果,因为没有返回值
}

是否有一个简明的定义允许
ValueType
充当一个真正的类型?

您能做的最好的事情就是这样——编写一个帮助器别名来包装被轻视的类型名

模板
使用char\u t=typename t::ValueType;
//方法,实际上什么都不做
模板
//我希望能够将值类型直接用作类型
void DoSomethingWithAnyString(StringType字符串,常量字符*数据添加)
{
StringType string2=字符串+数据添加;
//即使加法有效,也没有效果,因为没有返回值
}

您所能做的最好的事情就是这样——编写一个帮助器别名来包装被轻视的类型名

模板
使用char\u t=typename t::ValueType;
//方法,实际上什么都不做
模板
//我希望能够将值类型直接用作类型
void DoSomethingWithAnyString(StringType字符串,常量字符*数据添加)
{
StringType string2=字符串+数据添加;
//即使加法有效,也没有效果,因为没有返回值
}

错误告诉您要写的是
const-typename-StringType::ValueType*dataToAdd
,因为
StringType
对解析器来说是不透明的。@Quentin可以通过不同的定义ValueType来避免这种要求吗?每次使用时都要写typename似乎很烦人,也会让人分心,因为这在变量名中并不常见。不,但您可以使用ValueType=typename StringType::ValueType定义
模板,然后在代码中使用
ValueType
。执行错误显示的两项操作…?@TomášZato在blockscope中可以定义新别名。在您的示例中,可以使用第二个模板参数
typename ValueType=typename StringType::ValueType
。错误告诉您要编写的是
const typename StringType::ValueType*dataToAdd
,因为
StringType
在这一点上对解析器来说是不透明的。@Quentin可以通过不同的定义ValueType来避免这种要求吗?每次使用时都要写typename似乎很烦人,也会让人分心,因为这在变量名中并不常见。不,但您可以使用ValueType=typename StringType::ValueType定义
模板,然后在代码中使用
ValueType
。执行错误显示的两项操作…?@TomášZato在blockscope中可以定义新别名。在您的示例中,可以使用第二个模板参数
typename ValueType=typename StringType::ValueType
。我试图在
imysting
中直接执行类似操作,但仍然无法使用
StringType::char\u type
。我很困惑,为什么有时候重复这个字体名是有效的,有时候却不行。@TomášZato,你只需要接受
,所以标准说:
:P。更严重的是,在模板内部,你不能使用
typename
,因为它不是独立的名称。yetI试图在
imysting
中直接做类似的事情,但我仍然不能使用
StringType::char\u type
。我很困惑,为什么有时候重复typename是有效的,有时候不是。@TomášZato,好吧,你只需要接受
所以标准说eth
:P。更严重的是,在模板内部,你不能使用
typename
,因为它还不是从属名称
// 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
}