我想测试一个类型是否可以传递给某个函数,但我想在函数查找上使用 ADL 并包含来自某个命名空间的函数。
考虑这段代码:
#include <utility>
#include <vector>
template<class T>
concept Swappable = requires(T& a, T& b)
{
swap(a,b);
};
static_assert(Swappable<std::vector<int>>); // #1
static_assert(Swappable<int>); // #2
Run Code Online (Sandbox Code Playgroud)
#1 成功,它发现std::swapbecausestd是 的关联命名空间std::vector<int>。但 #2 失败了,内置类型没有关联的命名空间。
我该怎么写这样的东西:
template<class T>
concept Swappable = requires(T& a, T& b)
{
using std::swap; // illegal
swap(a,b);
};
Run Code Online (Sandbox Code Playgroud)
AFAIK,您不允许在 require 表达式中使用 using 声明。
(注意,虽然对此有一个完美的标准 C++ 概念,但std::swappable此示例swap仅用于说明。我并不是特别想测试某些东西是否实际上是可交换的,我只是想找到一种方法来实现这样的概念其中自定义函数在已知命名空间中具有默认实现,但可能在关联的命名空间中具有重载。)
编辑作为一种解决方法,我可以在一个单独的名称空间中实现这个概念,其中的名称被拉入。对此不太满意,但它有效。
namespace detail
{
using std::swap;
template<class T>
concept Swappable = …Run Code Online (Sandbox Code Playgroud) 我正在编写一个概念,检查类型是否可以在组成 2 个函数的表达式中使用:
template<typename T>
concept C = requires(T t) {
f(g(t));
};
Run Code Online (Sandbox Code Playgroud)
即,我想检查对于给定的t类型 的对象T,我是否可以调用g(t),然后使用结果值作为 的参数f。例如,
auto g(int) -> float;
auto g(char) -> double;
void f(float);
void f(double) = delete;
static_assert(C<int>); // g(int) returns a float, so f(float) is called.
static_assert(not C<char>); // g(char) returns a double, but f(double) is deleted
Run Code Online (Sandbox Code Playgroud)
这很好用。
但是,我想拆分对fand的调用g,因为 1)g可能需要额外的参数(不依赖于),从而导致冗长T的调用,2) 我可能想在g概念,所以我不想多次重复调用。
像下面这样的天真尝试
auto res = g(t);
f(res);
Run Code Online (Sandbox Code Playgroud)
和 …
在下面的代码中,类A有一个私有成员函数f。我想编写一个静态断言来检查该函数是否可以从当前上下文访问(正如对此问题的评论中所建议的那样)。
类似的情况还有3个,都是基于requires-表达式:
class A{ void f(); };
// #1: accepted by all
static_assert( { return requires(decltype(x) a){ a.f(); }; }(A{}) );
// #2: rejected by Clang:
static_assert( { return requires(A a){ a.f(); }; }(nullptr) );
// #3: rejected by all
static_assert( { return requires(A a){ a.f(); }; }(nullptr) );
Run Code Online (Sandbox Code Playgroud)
案例 #3(以及 Clang 中的案例 #2)被拒绝并出现错误:
error: 'f' is a private member of 'A'
Run Code Online (Sandbox Code Playgroud)
演示: https: //gcc.godbolt.org/z/Mxs4P7x8s
为什么需求表达式在模板和非模板中的行为不同(案例 #1 和 #3)?#2 中哪个编译器是正确的?
以下代码是否需要 T 的隐式复制构造函数,因为参数是按值传递的?或者它的行为类似于 decltype 并且不涉及真正的构造?
template<typename T>
concept Addable = requires (T a, T b){ a + b; };
Run Code Online (Sandbox Code Playgroud) 以下无法编译。
template <typename... U>
requires requires(U... x) { (std::to_string(x) && ...); }
auto to_string(const std::variant<U...>& value) {
return std::visit([](auto&& value) {
return std::to_string(std::forward<decltype(value)>(value));
}, value);
}
int main() {
std::variant<int, float> v = 42;
std::cout << to_string(v) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/Wvn6E3PG5
如果我将直接的 require 表达式转换为一个概念,它就可以正常工作。
template<typename T, typename... U>
concept to_stringable = requires(U... u) { (std::to_string(u) && ...); };
template <to_stringable... U>
auto to_string(const std::variant<U...>& value) {
return std::visit([](auto&& value) {
return std::to_string(std::forward<decltype(value)>(value));
}, value);
}
int main() {
std::variant<int, float> …Run Code Online (Sandbox Code Playgroud)