I have a class template that take a variadic number of template arguments. The class has some functions that take arguments corresponding to the class's template parameters. I would like these functions to bind to both lvalues and rvalues. How can I achieve this?
template<class ...C>
class Graph {
public:
Graph(C &...Context); // <- Only lvalues
Graph(C &&...Context); // <- Only rvalues
Graph(auto &&...Context); // <- Both lvalues and rvalues, but does not enforce that the types correspond to ...C
};
It doesn't seem to be possible to create a concept
inside the class. Can I create a concept outside the class and pass both the class template pack and the function template pack and verify them in some way? Or can I can add a requires
clause to the function that can solve it?
I have found some similar questions, but they are quite old, so there are no answers using concept
s.
It sounds like what you want is
template<class... C>
class Graph {
public:
template<class... Ts>
requires (std::same_as<Ts&, C&> and ...)
Graph(Ts&&... Context);
};
This exploits reference collapsing rules for concision.
If you want, you can write a concept for this (here written out in full):
template<class T, class U>
concept same_as_or_lvalue_reference_to = std::same_as<T, U> or std::same_as<T, U&>;
template<class... C>
class Graph {
public:
Graph(same_as_or_lvalue_reference_to<C> auto&&... Context);
};