使用 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;
}
您可以在一个概念中使用两个不同的 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
}
有没有人知道如何创建一个 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;
}
您可以在一个概念中使用两个不同的 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
}