如何删除C++概念
我正在尝试实现一个小型网络库来学习概念,并且我正在尝试找到一种方法来定义简洁的概念,而不必在依赖的概念上携带模板参数。例如,我有以下概念:
template <typename ValueT>
concept bool Value = true;
template <typename BufferT>
concept bool Buffer = requires(BufferT buf)
{
{ buf.Size() } -> std::size_t;
{ buf.Capacity() } -> std::size_t;
{ buf.Put(Value</* How can I resolve this to any value */>) } -> bool;
{ buf.Take(Value</* How can I resolve this to any value */>) } -> bool;
};
template <typename ReadableT>
concept bool Readable = requires(ReadableT r)
{
{ r.Read(Buffer</* How can I resolve this to any buffer */>) } -> void;
};
template <typename WritableT>
concept bool Writable = requires(WritableT w)
{
{ w.Write(Buffer</* How can I resolve this to any buffer */>) } -> void;
};
template <typename ChannelT>
concept bool Channel = requires(ChannelT chan)
{
requires Readable<ChannelT>;
requires Writable<ChannelT>;
};
如何在不显式拥有模板参数的情况下定义Value
和Buffer
概念?这有可能吗?我会直觉地这样写:
template <typename ReadableT>
concept bool Readable = requires(ReadableT r)
{
template <typename ValueT>
{ r.Read(Buffer<ValueT>) } -> void;
};
但这不能编译(显然),并且我找不出正确的语法。
编辑:我觉得正确的语法是这样的:
template <typename BufferT>
concept bool Buffer = requires(BufferT buf, Value val)
{
{ buf.Size() } -> std::size_t;
{ buf.Capacity() } -> std::size_t;
{ buf.Put(val) } -> bool;
{ buf.Take(val) } -> bool;
};
但GCC(8.3.0)打印此消息:
internal compiler error: in synthesize_implicit_template_parm, at cp/parser.c:39141
concept bool Buffer = requires(BufferT buf, Value val)
^~~~~
Please submit a full bug report, with preprocessed source if appropriate.
解决方案
我的想法是我应该能够将任何结构、整数、字符串或任何东西真正放入缓冲区
这不是一个概念能够回答的问题。它也不是故意的。
概念用于约束模板。在某种程度上,模板应该知道它在做什么。特定的模板实例化不适用于"任何结构、整数或字符串";它适用于特定类型,这些类型由其模板参数和依赖于它们的表达式定义。概念也是如此。
请考虑如下模板:
template<typename Buff, typename Iterator>
void InsertIntoBuffer(Buff &buf, Iterator beg, Iterator ed)
{
for(; beg != ed; ++beg)
buf.Put(*beg);
}
此函数要对Buff
施加的约束是NOT"具有可以接受任何对象的Put
函数。"实际约束是"有一个Put
函数,它可以接受Iterator
的operator*
返回的内容。"
因此,"放置"和"获取"不仅仅是对Buff
的约束;它还需要知道正在"放置"或"获取"的内容。
换句话说,受约束的不是类型,而是操作作为一个整体受到约束。
所以你会对Buffer
有一个基本约束,这是一个有大小和容量的东西。但您还应该有一个PutBuffer
约束,该约束要求Buffer
可以Put
给定类型。
同样,Readable
实际上是ReadableFromBuffer
,其中提供了缓冲区类型。
相关文章