标签: forwarding-reference

使用默认参数转发引用?

我在尝试弄清楚如何指定转发引用(以前由 Scott Meyers 称为通用引用)的默认参数时遇到困难。

这是尝试做我想做的事情的代码示例:

struct encoder_t {

} const encoder = {};

struct validator_t {

} const validator = {};

struct test {

    template <typename Range, typename Encoding, typename Validation>
    test ( Range&& range, Encoding&& encoding = encoder, Validation&& validation = validator ) {

    }

};

int main() {

    test( "woof" );

}
Run Code Online (Sandbox Code Playgroud)

也可在 Coliru 上购买

仔细检查这些错误,您发现可以通过默认模板参数来使其工作,然后默认构造参数:

// Works! But the syntax is strange... potential ramifications/deduction mishaps?
// Is this the "proper" way to default these …
Run Code Online (Sandbox Code Playgroud)

c++ templates constructor default-arguments forwarding-reference

5
推荐指数
1
解决办法
587
查看次数

类模板的模板参数推导的陷阱

我正在阅读有关类模板的模板参数推导的论文http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html。这个功能是 C++17 标准中的,有些事情让我感到困惑。

template <typename T>
class Something {
public:

    // delete the copy and move constructors for simplicity
    Something(const Something&) = delete;
    Something(Something&&) = delete;

    explicit Something(T&&) { ... }
    explicit Something(const T&) { ... }

    template <typename U, typename EnableIfNotT<U, T>* = nullptr>
    Something(U&&) { ... }
};
Run Code Online (Sandbox Code Playgroud)

鉴于上面的代码,如果有人尝试像这样实例化上述模板的实例

auto something = Something{std::shared_ptr<int>{}};
Run Code Online (Sandbox Code Playgroud)

右值引用重载总是会被调用吗?由于考虑扣除的过载集是

template <typename T>
Something<T> F(T&&) { ... }
template <typename T>
Something<T> F(const T&) { ... }
template <typename T, typename U, …
Run Code Online (Sandbox Code Playgroud)

c++ templates forwarding forwarding-reference c++17

5
推荐指数
1
解决办法
284
查看次数

C++:通用(转发)引用中不允许使用 const

我正在阅读这个 stackoverflow 答案const T&&,其中给出了不是通用(转发)参考的一个原因:

允许 const T&& 充当转发引用,将无法重载仅采用右值引用作为参数的模板函数。

我不知道这是什么意思。我想这意味着同一个函数(模板)有两个重载,其中一个重载作为参数const T&&。我还假设这些重载之一将始终被调用,而另一个永远不会被调用。

如果我的假设是正确的,那么这两个重载函数是什么?或者如果我错了,引用的段落实际上是什么意思?

谢谢。

c++ forwarding-reference

5
推荐指数
1
解决办法
241
查看次数

通过元组完美转发参数

我有一个理想情况下应如下所示的函数:

\n
template<typename... t_buffers, t_function function>\nvoid iterate_buffers(t_buffers &&... buffers, t_function &&function);\n
Run Code Online (Sandbox Code Playgroud)\n

但是,除非参数包类型位于最后,否则无法推断出参数包类型,因此我的函数签名如下:

\n
template<typename... t_buffers_and_function>\nvoid iterate_bufferes(t_buffers_and_function &&... buffers_and_function);\n
Run Code Online (Sandbox Code Playgroud)\n

然后参数会被重新排列,以便函数排在第一位。为了执行此改组,我使用了此处描述的技术,但在尝试转发元组时遇到了问题。

\n

这是一个存在问题的简化示例:

\n
template<typename... t_args>\nvoid inner(std::tuple<t_args &&...> args) {};\n\ntemplate<typename... t_args>\nvoid outer(t_args &&... args) {\n    inner(std::forward_as_tuple(std::forward<t_args>(args)...));\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果我传递右值(例如通过调用outer(1, 2);),它会按预期工作。但是,如果我传递左值 ( int x = 1; int y = 2; outer(x, y);),则会出现以下语法错误:

\n
error: could not convert \xe2\x80\x98std::forward_as_tuple(_Elements&& ...) [with _Elements = {int&, int&}]((* & std::forward<int&>((* & args#1))))\xe2\x80\x99 from \xe2\x80\x98std::tuple<int&, int&>\xe2\x80\x99 to \xe2\x80\x98std::tuple<int&&, int&&>\xe2\x80\x99\ninner(std::forward_as_tuple(std::forward<t_args>(args)...));\n~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n
Run Code Online (Sandbox Code Playgroud)\n

因此forward_as_tuple …

c++ tuples variadic-templates perfect-forwarding forwarding-reference

5
推荐指数
0
解决办法
799
查看次数

什么语言规则规定模板化数组&amp;&amp;函数参数中的“T&amp;&amp;”不是转发引用?

我正在使用的静态分析工具提示我需要std::forward调用链中以下函数的参数:

template<typename T, std::size_t size>
constexpr void f(T (&& arr)[size]) { /* linter: use std::forward on 'arr' here */ }
Run Code Online (Sandbox Code Playgroud)

因为它将函数参数类型标识为转发引用。

然而,对多个编译器的简单测试表明,这不是转发引用。下面的例子

void g() {
    int a[3]{1, 2, 3};
    f(a);  // #1
}
Run Code Online (Sandbox Code Playgroud)

#1在(DEMO )处被拒绝,明确指出函数参数是右值引用:

 error: cannot bind rvalue reference of type 'int (&&)[3]' to lvalue of type 'int [3]'
Run Code Online (Sandbox Code Playgroud)

问题

  • 哪些语言规则控制着上面T&&的模板化数组函数&&参数f不是转发引用?

c++ templates language-lawyer forwarding-reference

5
推荐指数
1
解决办法
104
查看次数

如何将类型约束和隐式转换与C++ 11通用引用相结合?

在函数中我需要区分左值和右值引用,所以明显的路径是重载:

void myfunc(A&& a);
void myfunc(const A& a);
Run Code Online (Sandbox Code Playgroud)

这具有完全所需的行为,具有良好定义的类型和隐式转换.然而,代码重复太多,我宁愿将相关决策封装在内部,只保留一个函数,因此通过通用引用可能是一个选项:

template <typename A>  void myfunc(A&& a);
Run Code Online (Sandbox Code Playgroud)

然而,这有一个令人遗憾的缺点,即现在任何对象都可以作为第一个参数传递,因此可以通过enable_if强加约束:

template <typename T, class  = typename enable_if<
    is_same<typename remove_const<typename    remove_reference<T>::type>::type, A>::value,
    T>::type>   
void myfunc( T&&  a);
Run Code Online (Sandbox Code Playgroud)

这几乎似乎可以完成这项工作,但是(我想已经通过模板化)我们已经失去了一个很好的重载属性,可以触发隐式转换构造函数到类型A(比如来自类型C参数).重载不是一个选项,因为某些函数可能有3个或更多A &&参数,无意处理组合爆炸.隐式转换可以以某种方式恢复吗?当然,一种解决方法可能是例如为A添加其他允许的参数类型,并在main函数中执行任何所需的转换,但这是侵入性的,丑陋的,明确的含义并产生混淆(原始C参数可能是左值[reference]并通过转换产生右值).有更好的方法吗?

c++ c++11 universal-reference forwarding-reference

4
推荐指数
1
解决办法
211
查看次数

转发引用不是被推导为 r 值引用吗?

我有一个关于转发引用的具体问题。(我认为)我理解 r 值引用和std::move,但我无法理解转发引用:

#include <iostream>
#include <utility>

template <typename T> class TD; // from "Effective Modern C++"

void consume(const int &i) { std::cout << "lvalue\n"; }
void consume(int &&i)      { std::cout << "rvalue\n"; }

template <typename T>
void foo(T&& x) {
//    TD<decltype(x)> xType; - prints int&&
    consume(x);
}

int main() {
    foo(1 + 2);
}
Run Code Online (Sandbox Code Playgroud)

Tint,没关系。如果x是 type int&&,为什么它打印“lvalue”而我们需要std::forward?我的意思是,从哪里转换int&&const int&这里?

c++ perfect-forwarding c++11 forwarding-reference

4
推荐指数
1
解决办法
115
查看次数

我想移动语义,但我得到了隐藏复制语义的通用参考

当我想要使用函数参数复制语义const T&或使用函数参数移动语义时,如何处理通用引用T&&。后者隐藏了第一个。

下面是带有代数向量运算符的示例代码。

#include <array>
#include <iostream>


template<typename T>
void neg(T &a) { for (auto &i : a) i = -i; }

// object 'a' remains available
template<typename T>
auto operator-(const T &a) { std::cout << "1\r\n"; T b = a; neg(b); return b; }

// object 'a' terminates its life
template<typename T>
auto operator-(T &&a) { std::cout << "2\r\n"; neg(a); return std::move(a); }

// make an rvalue
template<typename T1, typename T2>
auto operator+(const T1 &a, …
Run Code Online (Sandbox Code Playgroud)

c++ forwarding-reference

4
推荐指数
1
解决办法
98
查看次数

C++20 和(通用)引用中的柯里化

这是我使用 C++20 进行柯里化的实现:

#include <concepts>
#include <functional>

constexpr auto
curry(std::invocable auto f)
{
  return f();
}

constexpr auto
curry(auto f)
{
  return [=](auto x) { return curry(std::bind_front(f, x)); };
}

constexpr int
f(int a, int b, int c)
{
  return a * b * c;
}

constexpr auto
g(auto... args)
{
  return (1 * ... * args);
}

constexpr int
h()
{
  return 42;
}

int
main()
{
  static_assert(curry(f)(2)(3)(7) == 42);
  static_assert(curry(g<int, int, int, int>)(1)(2)(3)(7) == 42);
  static_assert(curry(h) == 42); …
Run Code Online (Sandbox Code Playgroud)

c++ currying forwarding-reference c++20

4
推荐指数
1
解决办法
223
查看次数

C++ 模板中的 auto&amp;&amp; 与 constrained auto&amp;&amp;

MSVC /std:c++20 报告约束自动&& 的错误如下所示

#include<concepts>

class Base { public: Base() {} };
class Derived : public Base { public: Derived() {} };

template<typename T> concept con = std::is_class_v<T>
&& std::derived_from<T, Base>;
void f(con auto&& x) {}

int main()
{
   f(Derived()); // r value: Ok

   Derived d;
   f(d); // l-value: no matching overloaded function found
}
Run Code Online (Sandbox Code Playgroud)

从“con auto&&”中删除“con”,上面的代码编译没有错误。我想了解为什么向 auto&& 模板参数添加约束会将其从“通用引用”更改为仅 R 值引用。此行为符合 C++20 标准还是 MSVC 独有的行为?

在互联网上搜索 C++ 论坛,没有找到任何解释这种特定语言用例的内容。然而,可能有一些我错过或没有注意到的事情。

c++ forwarding-reference c++20

4
推荐指数
2
解决办法
89
查看次数