使用 C++ 概念检查其他类型上的函数是否存在

Check for function existance on other type using C++ concepts

有没有人知道如何创建一个 C++ 概念 T 使得函数 g 仅在存在重载时为类型为 T 的参数 t 定义B 中的 f 接受参数 t?

struct A1 {};
struct A2 {};
struct B {
    void f(A1 a1) {}
};
void g(T t) {
    B b;
    b.f(t);
}

例如,我想为 std::stringstream 接受的所有内容定义一个 to_string,并定义类似

的内容
std::string to_string(T t) {
    std::stringstream ret;
    ret << t;
    return ret.str();
}

所有关于概念的例子都处理了更简单的情况,即要求一个类型存在一个函数,而在这种情况下,我们想检查另一个类型是否存在一个函数。

如果你想检查类型是否可流式传输,你可以这样:

#include <iostream>
#include <concepts>
#include <sstream>

template <typename T> 
concept Streamable = requires (T x, std::ostream &os) { os << x; };

struct Foo {};
struct Bar {};

std::ostream& operator<<(std::ostream& os, Foo const& obj) {
    // write obj to stream
    return os;
}

template <Streamable T>
std::string to_string(T t) {
    std::stringstream ret;
    ret << t;
    return ret.str();
}

int main() {
    Foo f;
    Bar b;

    to_string(f);
    to_string(b); // error

    return 0; 
}

Demo

您可以在一个概念中使用两个不同的 type 占位符,以要求其中一个类型占位符的实例存在成员函数,以及所述成员函数的参数以匹配另一个占位符的类型。例如:

#include <iostream>

template<typename T, typename U>
concept HasMemFnConstFoo = requires(const T t, const U u) {
    t.foo(u);
};

template<typename U>
struct Bar {
    template <typename T>
    static void bar(const T& t)
    {
        if constexpr (HasMemFnConstFoo<T, U>) { t.foo(U{}); }
        else { std::cout << "foo() not defined\n"; }
    }
};

struct A1 {};
struct A2 {};
struct B1 {
    void foo(const A1&) const { std::cout << "B1::foo()\n"; }
};
struct B2 {
    void foo(const A1&) { std::cout << "B2::foo()\n"; }
};
struct B3 {
    void foo(A1&) const { std::cout << "B3::foo()\n"; }
};

int main() {
    Bar<A1>::bar(B1{});  // B1::foo()
    Bar<A2>::bar(B1{});  // foo() not defined
    Bar<A1>::bar(B2{});  // foo() not defined [note: method constness]
    Bar<A2>::bar(B2{});  // foo() not defined
    Bar<A1>::bar(B3{});  // foo() not defined [note: argument constness]
    Bar<A2>::bar(B3{});  // foo() not defined
}