有没有办法在C++中实现“部分递归”函数约束?

问题描述 投票:0回答:1

我正在编写一个策略类,

TrivialSerializer
,稍后将在 C++ 中插入一个函数。该策略需要将其他策略在一定程度上指定类型的对象序列化,并将其写入流中。只有对象值需要序列化,因为对象的布局和结构是预先指定的。

为了实现此目的,我使用通用模板化静态成员函数

template <typename T> static void write(output_stream_t& stream, T const& object)
来序列化任意对象,仅模板的某些特化和重载不会被删除。例如,我对表单的大小范围有一个通用的专业化

template <ranges::sized_range T>
requires requires(output_stream_t& stream, ranges::range_value_t<T> value) {
    { write<ranges::range_value_t<T>>(stream, value) };
}
static void write(output_stream_t& stream, T const& range);

我对元组和积分有类似的专业化,以及应单独处理的特定类的重载。

这里的问题是语言解析约束的方式与我编写它们时的意图不符。像

vector<vector<int>>
这样的类型不会尝试使用大小范围的特化,因为它的值类型是
vector<int>
,在评估 require 子句时,其特化尚未实例化。当然,如果类型
vector<int>
在除特定的 require 子句之外的任何地方使用,它本身确实会使用正确的重载。调用
write(output_stream_t&, vector<vector<int>> const&)
时的预期行为是让类型检查器考虑大小范围的专业化并寻找调用
write(output_stream_t&, vector<int> const&)
的方法,这会导致它再次考虑大小范围的专业化并寻找调用
 的方法write(output_stream_t&, int const&)
,它以积分专业化的形式找到,这导致它得出结论:
vector<vector<int>>
可以用作第二个参数
write

我的主要问题是:有没有办法让 C++ 约束检查器执行这种对重载的“递归”考虑,或者我是否必须在

write
的函数体内求助于运行时约束检查?我的第二个问题是:委员会和工作组的工作中是否有任何建议来解决这个问题?

我已经看过这个问题,它离遇到我遇到的同样问题不远了,但在这种情况下它没有提供任何解决方案。

c++ serialization template-meta-programming c++-concepts
1个回答
0
投票

正如 @HolyBlackCat 指出的,使用具有专业化和静态成员函数的类(并使用单独的函数作为专业化的更好接口)可以解决问题。范围的类专业化现在如下所示:

template <sink_c sink_t, std::ranges::sized_range value_t>
requires requires(sink_t& sink, std::ranges::range_value_t<value_t> element) {
    { DefaultWrite<sink_t, std::ranges::range_value_t<value_t>>::call(sink, element) };
}
struct DefaultWrite<sink_t, value_t> {
    static void call(sink_t& sink, value_t const& value);
};
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.