数组的部分模板成员特化

3

我正在尝试创建一个适用于不同数据类型的模板类:

template <typename TDataType>
class CBaseProperty : public CBasePropertyBase

现在这个类有一个针对像这样的数组的特殊化:

template <typename TDataType, u32 TSize>
class CBaseProperty<TDataType[TSize]> : public CBasePropertyBase

现在我想为字符串编写一个特定成员函数的专门版本:
template <> b8 CBaseProperty<string>::setValue(const void* _pVal)

当我尝试为字符串数组的部分特化指定这个成员时:

template <u32 _TSize> b8 CBaseProperty<string[TSize]>::setValue(const void* _pVal)

我遇到了3个错误:
错误1: 错误 C3860:在类模板名称后列出的模板参数列表必须按照模板参数列表中使用的顺序列出参数。 错误2: 错误 C2995:b8 CBaseProperty<TDataType>::setValue(const void*):函数模板已经被定义过。 错误3: 错误 C3855:CBaseProperty<TDataType>:模板参数TDataType与声明不兼容。
我究竟做错了什么?根据我的所有资料,我部分成员特化的语法是正确的。
感谢任何帮助。

你能展示一下字符串的定义吗?它是内置类型的别名还是类模板?如果它是一个类模板,那么你使用了错误的括号类型 [ 而不是 <。 - odinthenerd
还有,什么是u32?尝试使用std::size_t代替u32。 - odinthenerd
@PorkyBrain: 抱歉,我忘记了:typedef unsigned int u32;而我的字符串是一个 std::string。 - Thomas B.
@quantdev:我尝试创建一个类,可以将数据保存为普通数据或数组形式:我想要能够编写:CBaseProperty<int> VarName; 以及 CBaseProperty<int[4]> VarName; 我希望使用两个不同的模板类中存储的不同方法和数据。例如,数组类将包含一个数组访问运算符[]。 - Thomas B.
@ThomasB.:你不应该随意使用typedef类型,特别是当它们有着众所周知的名称时。此外,名称u32已经内置了这样一个假设,即该类型将是32位宽度,而对于unsigned int并不保证如此。标准库实际上提供了具有这种保证、广为人知且跨平台的类型。你要找的是std::uint32_t。最后,如果你选择一个类型来表示某个东西的大小,你应该始终选择std::size_t - Robert Allan Hennigan Leahy
2个回答

2

你只能通过提供所有模板参数(你将长度作为参数留下)来专门化单个成员函数,它会强制你在这里指定数组长度。

因此,如果你需要一个针对字符串数组的特定版本,保留长度作为参数,你首先需要针对字符串数组对类模板进行专门化。

就我所理解的,解决方案可以简化为以下最小示例:

template<class T>
class foo
{
    public:
    void tell() { cout << "general\n"; }
    void base() { cout << "ok"; }
};

template<class T, std::size_t N>
class foo<T[N]>
{
    public:
    void tell() { cout << "special arrays\n"; }
};

template<std::size_t N>
class foo<std::string[N]>
{
    public:
    void tell() { cout << "special string arrays\n"; }
};

template<>
void foo<std::string>::tell()
{
  cout << "string\n";   
}

int main()
{
  foo<std::string[2]> f;   
  f.tell();

  return 0;
}

输出:

特殊字符串数组


非常感谢,这正是我想知道的。 - Thomas B.

0
template <u32 _TSize> b8 CBaseProperty<string[TSize]>::setValue(const void* _pVal)

当字符串是 std::string 的别名时,这不是有效的代码,因为 std::string 是可变长度的,所以您可以在编译时对其长度进行特化。

template <typename TDataType, u32 TSize>
class CBaseProperty<TDataType[TSize]> : public CBasePropertyBase

这可能可行,但是存在风险,因为 std::size_t 类型是实现定义的,所以如果您的 u32 类型(您在评论中说是无符号整数)与 std::size_t 不同,它们可能不匹配。

查看实时示例:http://ideone.com/ZH4v6x


2
这个模板不应该用于长度不同的字符串,而是用于一个包含多个字符串数组的类,就像我写的时候:string[5] MyStrings; - Thomas B.
你的实时示例正是我已经在我的类本身中完成的。现在我想要一个针对字符串作为数据类型调用的方法版本。并且我希望这个方法对于数组和非数组类是不同的。 - Thomas B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接