英文:
Bind both lvalues and rvalues to variadic class template parameter
问题
我有一个类模板,可以接受可变数量的模板参数。该类具有一些函数,这些函数接受与类模板参数相对应的参数。我希望这些函数能绑定到左值和右值。我该如何实现这一点?
```c++
template<class ...C>
class Graph {
public:
Graph(C &...Context); // <- 仅限左值
Graph(C &&...Context); // <- 仅限右值
Graph(auto &&...Context); // <- 既可以接受左值也可以接受右值,但不强制要求类型与...C对应
};
似乎不可能在类内部创建一个concept
。我可以在类外部创建一个concept
,并将类模板包和函数模板包都传递进去,以某种方式进行验证吗?还是我可以在函数中添加一个requires
子句来解决这个问题?
我找到了一些类似的问题,但它们都很旧,所以没有使用concept
的答案。
<details>
<summary>英文:</summary>
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?
```c++
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.
答案1
得分: 4
Concept std::constructible_from
might help:
template <class... C>
class Graph {
public:
template <typename... Ts>
requires((std::constructible_from<C, Ts> && ...))
Graph(Ts&&...);
};
or more strict std::convertible_to
:
template <class... C>
class Graph {
public:
template <typename... Ts>
requires((std::convertible_to<Ts, C> && ...))
Graph(Ts&&...);
};
or std::same_as
:
template <class... C>
class Graph {
public:
template <typename... Ts>
requires(((std::same_as<Ts&&, C&&>
|| (std::same_as<Ts&&, C&> /*&& !std::is_rvalue_reference_v<C>*/))
&& ...))
Graph(Ts&&...);
};
英文:
Concept std::constructible_from
might help:
template <class... C>
class Graph {
public:
template <typename... Ts>
requires((std::constructible_from<C, Ts> && ...))
Graph(Ts&&...);
};
or more strict std::convertible_to
template <class... C>
class Graph {
public:
template <typename... Ts>
requires((std::convertible_to<Ts, C> && ...))
Graph(Ts&&...);
};
or std::same_as
:
template <class... C>
class Graph {
public:
template <typename... Ts>
requires(((std::same_as<Ts&&, C&&>
|| (std::same_as<Ts&&, C&> /*&& !std::is_rvalue_reference_v<C>*/))
&& ...))
Graph(Ts&&...);
};
答案2
得分: 1
听起来你想要的是
```c++
template<class... C>
class Graph {
public:
template<class... Ts>
requires (std::same_as<Ts&, C&> and ...)
Graph(Ts&&... Context);
};
这利用了引用折叠规则以简洁地实现。
如果你愿意,你可以为此编写一个概念(这里完整写出):
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);
};
<details>
<summary>英文:</summary>
It sounds like what you want is
```c++
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);
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论