如何使用 C++20 概念根据函数的返回类型执行不同的操作?

L0r*_*en2 3 c++ c++-concepts c++20

我想创建一个通用print(x)函数,它对于不同类型有不同的行为。

到目前为止,我所拥有的适用于所有容器类型,包括我自己编写的容器类型。然而,要么调用了“错误”的函数,要么由于不明确而无法编译。

这是我的代码:

#include <iostream>
#include <concepts>

class Container
{
    int x, y, z;
public:
    Container(int a, int b, int c) : x(a), y(b), z(c) {}
    Container() : x(0), y(0), z(0) {}
    std::size_t size() const { return 3; }
    const int& operator[] (std::size_t index) const { if(index == 0) return x; else if(index == 1) return y; else return z; }
    int& operator[] (std::size_t index) { if(index == 0) return x; else if(index == 1) return y; else return z; }
};

template<typename T>
concept printable_num = requires (T t, std::size_t s) 
{ 
    { t.size() } -> std::convertible_to<std::size_t>;
    { t[s] } -> std::same_as<int&>;
};
template<printable_num T>
void print(const T& t) {
    std::size_t i = 0;
    for(;i < t.size() - 1; i++)
        std::cout << t[i] << ", ";
    std::cout << t[i] << std::endl;
}
    

template<typename T>
concept printable = requires (T t, std::size_t s) 
{ 
    { t.size() } -> std::convertible_to<std::size_t>;
    { t[s] } -> std::convertible_to<char>;
};

template<printable T> 
void print(const T& t) {
    std::size_t i = 0;
    for(;i < t.size() - 1; i++)
        std::cout << t[i];
    std::cout << t[i] << std::endl;
}

int main()
{
    Container c{1, 2, 3};
    print(c);
    Container empty;
    print(empty);
    std::string s{"this is some string"};
    print(s);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如您所见,如果返回的类型operator[]是,我想打印分隔符int&。由于不明确,这不会编译。

有没有一种方法可以进行编译并让我到达我想要的位置(对于 std::string 调用不带分隔符的打印函数,对于我自己的容器类型调用带有分隔符的打印函数)?

Sto*_*ica 7

给定一个整数(或一的左值),您是否同意它可以转换为 a char?这些约束准确地检查了您让它们检查问题中的类型的内容。

解决这个问题的一种方法是通过约束包含。这意味着(以非常手波浪的方式),如果您的概念被编写为相同基本约束的共轭(或析取),则编译器可以规范化表达式以选择“更专业的表达式”。将其应用到您的示例中..

template<typename T>
concept printable = requires (T t, std::size_t s) 
{ 
    { t.size() } -> std::convertible_to<std::size_t>;
    { t[s] } -> std::convertible_to<char>;
};

template<typename T>
concept printable_num = printable<T> && requires (T t, std::size_t s) 
{ 
    { t[s] } -> std::same_as<int&>;
};
Run Code Online (Sandbox Code Playgroud)

请注意我们过去如何printable定义printable_num“更具体”的概念。运行这个例子,我们得到你想要的输出