我对容器类型有一个相对简单的概念定义,它接受特定的值类型:
template <typename T>
concept FooContainer = requires(T cont){
std::begin(cont);
std::end(cont);
requires std::is_same_v<typename T::value_type, Foo>;
};
我想定义一个可以接受两个参数的函数,每个参数都是满足这个概念的任何容器类型。到目前为止我已经
void func(const FooContainer auto& cont1, const FooContainer auto& cont2){
// ...
}
这工作得很好,我可以将任何我想要的左值或右值传递到 cont1 或 cont2 中,因为我认为 C++ 自动将
const lvalue reference
绑定到 rvalue
参数。不过我想知道这里如何利用完美转发,让值类别可以自动转发到函数中。
我知道转发引用只能在模板化函数中使用,但这对我来说有点困惑,因为参数已经是模板化概念......
我尝试在不同的地方添加
&&
:即在概念模板 typename T
中,但不确定它到底有什么作用。
您的
func
是一个函数模板。
转发引用是
T&&
类型的参数,其中T
是模板参数。我从您的代码中删除了一些多余的内容,以专注于本质:
#include <type_traits>
#include <iostream>
struct Foo {};
template <typename T>
concept FooContainer = requires(T){
requires std::is_same_v<typename std::remove_cvref_t<T>::value_type, Foo>;
};
struct Container {
using value_type = Foo;
};
void bar(const Container&) { std::cout << "hello &";}
void bar(Container&&) { std::cout << "hello &&"; }
void func(FooContainer auto&& cont1, FooContainer auto&& cont2){
bar(std::forward<decltype(cont1)>(cont1));
bar(std::forward<decltype(cont2)>(cont2));
}
int main() {
Container c;
func(c,Container{});
}
输出:
hello &hello &&
请注意,您必须决定您的概念是否应该与值或参考文献或两者相匹配。感谢 Jarod42 指出了这一点。我添加了
std::remove_cvref
来接受两者。