繁体   English   中英

使用具有循环依赖的 ADL 的 C++20 概念

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM