我想创建某种数据实用程序,它存储
std::stringstream
以及内容当前采用的格式。这将为您提供关于数据当前所具有的内容表示的类型安全性和 IntelliSense。基本上,它为每个操作(压缩、编码、解析等)创建或删除模板参数:
// content representations/states
enum class ContentTypes
{
binary = 1,
text = 2,
json = 3,
zlib = 4
};
template <ContentTypes... PreviousTypes>
class X
{
public:
X<ContentTypes::zlib, PreviousTypes...> zlib()
{
return X<ContentTypes::zlib, PreviousTypes...>();
}
};
template <ContentTypes... PreviousTypes>
class X<ContentTypes::zlib, PreviousTypes...> : public X<(ContentTypes::zlib, PreviousTypes)...>
{
public:
X<PreviousTypes...> decompress()
{
return X<PreviousTypes...>();
}
};
#include <string>
#include <iostream>
int main()
{
/// deterministic and compile-time safety as to what content type the data has
X<ContentTypes::binary> foo; // some binary data (X<ContentTypes::binary>)
auto compressed = foo.zlib(); // X<ContentTypes::zlib, ContentTypes::binary>
auto compressed2 = compressed.zlib(); // X<ContentTypes::zlib, ContentTypes::zlib, ContentTypes::binary>
auto decompressed = compressed2.decompress(); // X<ContentTypes::zlib, ContentTypes::binary>
auto decompressed2 = decompressed.decompress(); // X<ContentTypes::binary>
return 0;
}
您可能已经注意到,模板专业化中有一个错误:
class X<ContentTypes::zlib, PreviousTypes...> : public X<(ContentTypes::zlib, PreviousTypes)...>
这会导致错误的内容类型。如果你尝试编译上面的代码,你会得到一个错误,变量
decompressed
(实际上是X<ContentTypes::binary>
类型,而不是X<ContentTypes::zlib, ContentTypes::binary>
)没有属性decompress
。这是正确的,因为 X<ContentTypes::binary>
没有名为 decompress
的函数。我不知道如何将上层模板实例化的方法“继承”到下层模板实例化的方法而不以递归模板结束。
.../src/main.cpp:52:39: error: 'class X<ContentTypes::binary>' has no member named 'decompress'
52 | auto decompressed2 = decompressed.decompress(); // X<ContentTypes::binary>
| ^~~~~~~~~~
(ContentTypes::zlib, PreviousTypes)...
扩展,我认为这根本不正确,因为它只执行逗号运算符...如果您需要更多信息,请在评论中询问。 提前致谢! :)
感谢您的有用评论! 我收到了一个提示,让我找到了可行的解决方案:
enum class ContentTypes
{
binary = 1,
text = 2,
json = 3,
zlib = 4
};
template <ContentTypes... PreviousTypes>
class X;
template <ContentTypes... PreviousTypes>
class XBase
{
public:
X<ContentTypes::zlib, PreviousTypes...> zlib()
{
return X<ContentTypes::zlib, PreviousTypes...>();
}
};
template <ContentTypes... PreviousTypes>
class X : public XBase<PreviousTypes...>
{
};
template <ContentTypes... PreviousTypes>
class X<ContentTypes::zlib, PreviousTypes...> : public XBase<ContentTypes::zlib, PreviousTypes...>
{
public:
X<PreviousTypes...> decompress()
{
return X<PreviousTypes...>();
}
};
#include <string>
#include <iostream>
int main()
{
/// deterministic and compile-time safety as to what content type the data has
X<ContentTypes::binary> foo; // some binary data (X<ContentTypes::binary>)
auto compressed = foo.zlib(); // X<ContentTypes::zlib, ContentTypes::binary>
auto compressed2 = compressed.zlib(); // X<ContentTypes::zlib, ContentTypes::zlib, ContentTypes::binary>
auto decompressed = compressed2.decompress(); // X<ContentTypes::zlib, ContentTypes::binary>
auto decompressed2 = decompressed.decompress(); // X<ContentTypes::binary>
return 0;
}
以正确的方式完成的继承将创建一个递归模板,该模板会中止编译,因为派生类和父类的名称相同(
X
)。只需将父类重命名为Xbase
并继承它,这个问题就解决了。现在您只需要创建一个新的基本模板类 X
,它也继承自 XBase
即可使事情完成。