[英]C++20 concepts using ADL with circular dependency
我对使用 ADL 的概念有疑问。
编辑1:我提到ADL,因为parse
函数应该被用户定义的类型重载。
from_string_view_parsable
概念看不到下面的parse
函数,因为 ADL 不适用于它们。
这些函数需要在概念定义之前定义或前向声明,但是第二次重载存在循环依赖,因此无法完成。
https://godbolt.org/z/frn1jKv5E
#include <sstream>
#include <optional>
template <typename T>
concept from_string_view_parsable = requires(std::string_view sv, T& x) {
{ parse(sv, x) };
};
void parse(std::string_view input, int& out)
{
auto ss = std::stringstream{};
ss << input;
ss >> out;
}
template <from_string_view_parsable T>
requires std::default_initializable<T>
void parse(std::string_view input, std::optional<T>& out)
{
out = T{};
parse(input, *out);
}
template <from_string_view_parsable T>
void use_parse(T& t) {
parse("123", t);
}
int main() {
std::optional<int> x;
use_parse(x);
}
我正在尝试做的事情从根本上是错误的,或者是否有任何解决方法可以让我这样做?
您可以将requires
表达式推迟到可以向前声明的类型特征:
#include <sstream>
#include <optional>
#include <string_view>
#include <type_traits>
template <typename T>
struct is_from_string_view_parsable;
template <typename T>
concept from_string_view_parsable = is_from_string_view_parsable<T>::value;
void parse(std::string_view input, int& out)
{
auto ss = std::stringstream{};
ss << input;
ss >> out;
}
template <from_string_view_parsable T>
requires std::default_initializable<T>
void parse(std::string_view input, std::optional<T>& out)
{
out = T{};
parse(input, *out);
}
template <from_string_view_parsable T>
void use_parse(T& t) {
parse("123", t);
}
template <typename T>
struct is_from_string_view_parsable : std::bool_constant<
requires(std::string_view sv, T& x) {
{ parse(sv, x) };
}
> {};
int main() {
std::optional<int> x;
use_parse(x);
}
现在,我不确定这是否违反任何规则,但我认为不应该。 请注意,约束的评估不会在程序中的不同点发生变化。
由于不能前向声明概念,因此from_string_view_parsable
的定义必须出现在std::optional
重载之后。
相反,您可以使用requires 子句(或static_assert
)来约束parse(intput, *out)
必须格式正确,如下所示:
#include <sstream>
#include <optional>
void parse(std::string_view input, int& out)
{
auto ss = std::stringstream{};
ss << input;
ss >> out;
}
template <std::default_initializable T>
void parse(std::string_view input, std::optional<T>& out)
requires requires { parse(input, *out); }
{
out = T{};
parse(input, *out);
}
template <typename T>
concept from_string_view_parsable = requires(std::string_view sv, T& x) {
{ parse(sv, x) };
};
template <from_string_view_parsable T>
void use_parse(T& t) {
parse("123", t);
}
int main() {
std::optional<int> x;
use_parse(x);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.