我试图实现一个小型的网络库以了解概念,并且试图找到一种定义简洁概念的方法,而不必在依赖概念上携带模板参数。例如,我有以下概念:
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.
答案 0 :(得分:1)
我的想法是我应该能够将任何结构,整数或字符串或任何真正位于缓冲区中的东西
这不是一个概念能够回答的问题。也不是故意的。
概念旨在约束模板。模板在某种程度上应该知道它在做什么。特定的模板实例化不适用于“任何结构,整数或字符串”;它适用于特定类型,该类型由其模板参数和依赖于它们的表达式定义。概念也是如此。
因此请考虑这样的模板:
template<typename Buff, typename Iterator>
void InsertIntoBuffer(Buff &buf, Iterator beg, Iterator ed)
{
for(; beg != ed; ++beg)
buf.Put(*beg);
}
此函数要施加在Buff
上的约束不是不是“具有可以接受任何对象的Put
函数”。实际的约束条件是“具有一个Put
函数,该函数可以接受Iterator
的{{1}}返回的值。”
因此,“投入”和“接受”不仅是对operator*
的约束;它也需要知道正在“放”或“取”的东西。
换句话说,不是具有约束的类型。整个操作受到限制。
因此,您将拥有Buff
的基本约束,该约束具有大小和容量。但是您还应该有一个Buffer
约束,它强制要求PutBuffer
可以Buffer
给定类型。
类似地,Put
实际上是Readable
,其中提供了缓冲区类型。
答案 1 :(得分:0)
例如,您不能在类型上拥有无限的约束,例如它支持put(int)
,put(int*)
,put(int**)
,等。 。 (通常如何检查这种约束?)您真的不想宣称存在可以接受任何 put
的模板T
。 (传统的,不受约束的)语法表明它可以,几乎总是存在隐含的约束(或假设),这些隐含的约束(或假设)可以通过使用 some T
实例化来打破(请考虑诸如{{1 }}。
作为序列化的实际问题,您可以仅检查void() const
是否接受put
,int
和float
,还可以与代表人const char*
一起检查大概。