将左值和右值都绑定到可变参数类模板参数。

huangapple go评论70阅读模式
英文:

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&#39;s template parameters. I would like these functions to bind to both lvalues and rvalues. How can I achieve this?

```c++
template&lt;class ...C&gt;
class Graph {
public:
    Graph(C &amp;...Context); // &lt;- Only lvalues
    Graph(C &amp;&amp;...Context); // &lt;- Only rvalues
    Graph(auto &amp;&amp;...Context); // &lt;- 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 concepts.

答案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&&...);
};

Demo

or more strict std::convertible_to:

template <class... C>
class Graph {
public:
    template <typename... Ts>
    requires((std::convertible_to<Ts, C> && ...))
    Graph(Ts&&...);
};

Demo

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&&...);
};

Demo

英文:

Concept std::constructible_from might help:

template &lt;class... C&gt;
class Graph {
public:
    template &lt;typename... Ts&gt;
    requires((std::constructible_from&lt;C, Ts&gt; &amp;&amp; ...))
    Graph(Ts&amp;&amp;...);
};

Demo

or more strict std::convertible_to

template &lt;class... C&gt;
class Graph {
public:
    template &lt;typename... Ts&gt;
    requires((std::convertible_to&lt;Ts, C&gt; &amp;&amp; ...))
    Graph(Ts&amp;&amp;...);
};

Demo

or std::same_as:

template &lt;class... C&gt;
class Graph {
public:
    template &lt;typename... Ts&gt;
    requires(((std::same_as&lt;Ts&amp;&amp;, C&amp;&amp;&gt;
               || (std::same_as&lt;Ts&amp;&amp;, C&amp;&gt; /*&amp;&amp; !std::is_rvalue_reference_v&lt;C&gt;*/))
            &amp;&amp; ...))
    Graph(Ts&amp;&amp;...);
};

Demo

答案2

得分: 1

听起来你想要的是
```c++
template&lt;class... C&gt;
class Graph {
public:
    template&lt;class... Ts&gt;
    requires (std::same_as&lt;Ts&amp;, C&amp;&gt; and ...)
    Graph(Ts&amp;&amp;... Context);
};

这利用了引用折叠规则以简洁地实现。

如果你愿意,你可以为此编写一个概念(这里完整写出):

template&lt;class T, class U&gt;
concept same_as_or_lvalue_reference_to = std::same_as&lt;T, U&gt; or std::same_as&lt;T, U&amp;&gt;;

template&lt;class... C&gt;
class Graph {
public:
    Graph(same_as_or_lvalue_reference_to&lt;C&gt; auto&amp;&amp;... Context);
};

<details>
<summary>英文:</summary>

It sounds like what you want is
```c++
template&lt;class... C&gt;
class Graph {
public:
    template&lt;class... Ts&gt;
    requires (std::same_as&lt;Ts&amp;, C&amp;&gt; and ...)
    Graph(Ts&amp;&amp;... Context);
};

This exploits reference collapsing rules for concision.

If you want, you can write a concept for this (here written out in full):

template&lt;class T, class U&gt;
concept same_as_or_lvalue_reference_to = std::same_as&lt;T, U&gt; or std::same_as&lt;T, U&amp;&gt;;

template&lt;class... C&gt;
class Graph {
public:
    Graph(same_as_or_lvalue_reference_to&lt;C&gt; auto&amp;&amp;... Context);
};

huangapple
  • 本文由 发表于 2023年6月26日 14:08:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76553920.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定