Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ concept and perfect forwarding

I have a relatively simple concept definition of a container type which takes in a specific value type:

template <typename T>
concept FooContainer = requires(T cont){
    std::begin(cont);
    std::end(cont);
    requires std::is_same_v<typename T::value_type, Foo>;
};

And I would like to define a function that can take in two arguments, each being any container type that satisfy this concept. So far I have

    void func(const FooContainer auto& cont1, const FooContainer auto& cont2){
        // ...
    }

This works fine and I can pass in any lvalue or rvalue I want into either cont1 or cont2, as I think C++ automatically binds a const lvalue reference to an rvalue parameter. However, I am wondering how perfect forwarding can be utilized here, so that the value categories can be automatically forwarded into the function.

I knew that forwarding references can only be used in a templated function, but this gets a bit confusing for me as the parameters are already templated concepts...

I tried adding && at different places: i.e. in the template typename T for the concept, but not sure exactly what it does.

like image 855
jh0427 Avatar asked Oct 21 '25 03:10

jh0427


1 Answers

Your func is a function template.

A forwarding reference is a parameter of type T&& where T is a template argument. I removed a bit of cruft from your code to concentrate on the essential:

#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{});
}

Output:

hello &hello &&

Note that you have to decide if your concept should match values or references or both. Thanks to Jarod42 for pointing that out. I added std::remove_cvref to accept both.

like image 148
463035818_is_not_a_number Avatar answered Oct 22 '25 16:10

463035818_is_not_a_number



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!