如何处理 const T& 和 T&& 实例化到相同的签名?
How to deal with const T& and T&& instantiating to the same signature?
基本上我想提供来自 const 左值版本和右值引用版本的构造:
transform_iterator(const Functor& f, const Iterator& it) :
functor(f),
iterator(it)
{}
transform_iterator(Functor&& f, Iterator&& it) :
functor(f),
iterator(it)
{}
据我所知,右值引用版本不是通用引用。尽管如此,在这个电话站点上:
template <typename InputIt, typename OutputIt>
std::pair<InputIt, OutputIt> sliding_average(InputIt first, InputIt last,
const typename std::iterator_traits<InputIt>::difference_type window_length,
OutputIt d_first)
{
using value_type = typename std::iterator_traits<InputIt>::value_type;
auto divide = [&window_length](const value_type& value)
{
return value / window_length;
};
auto iterator = shino::transformer(divide, d_first); //transform_iterator<Functor, Iterator>
shino::sliding_window(first, last, iterator, window_length);
//^^ pass by value
编译器说右值引用版本最终成为 const 左值引用版本。
为了完整起见,这里是 sliding_average
的调用站点
sliding_average(v.begin(), v.end(), window_length, output.begin());
其中v
和output
都是int和double的向量,window_length
是std::size_t
。
当我删除 const 左值版本时,代码编译并正常工作。
此外,这段代码编译时两个构造函数都没有问题:
std::vector<std::string> v{"23", "25", "27"}; //just random numbers
std::vector<int> output(v.size());
auto string_to_int = [](const std::string& x)
{
return std::stoi(x);
};
auto conversion_iterator = shino::transformer(string_to_int, output.begin());
问题:如何解决?
在
auto iterator = shino::transformer(divide, d_first);
您总是要调用函数的 const 左值引用重载。原因是 d_first
是一个命名变量。这意味着它是一个 lvalue
即使它作为右值传递给函数。如果你想让一个命名变量成为右值,你需要使用 std::move
like
auto iterator = shino::transformer(divide, std::move(d_first));
我认为你对lvalues和rvalues的理解不正确。
您没有在您发布的代码中的任何地方使用 rvalue 调用 transform_iterator::transform_iterator
。
auto iterator = shino::transformer(divide, d_first);
// ^^^^^^^
// lvalue
要调用 rvalue 引用 重载,您需要一个 rvalue! std::move
可用于将 d_first
转换为 右值引用 - 示例:
auto iterator = shino::transformer(divide, std::move(d_first));
// ^^^^^^^^^^^^^^^^^^
// rvalue
这同样适用于您在编辑中添加的代码:
shino::sliding_window(first, last, iterator, window_length);
// ^^^^^^^^
// lvalue
你可能想要:
shino::sliding_window(first, last, std::move(iterator), window_length);
// ^^^^^^^^^^^^^^^^^^^
// rvalue
相关问题:
"What are rvalues, lvalues, xvalues, glvalues, and prvalues?"
基本上我想提供来自 const 左值版本和右值引用版本的构造:
transform_iterator(const Functor& f, const Iterator& it) :
functor(f),
iterator(it)
{}
transform_iterator(Functor&& f, Iterator&& it) :
functor(f),
iterator(it)
{}
据我所知,右值引用版本不是通用引用。尽管如此,在这个电话站点上:
template <typename InputIt, typename OutputIt>
std::pair<InputIt, OutputIt> sliding_average(InputIt first, InputIt last,
const typename std::iterator_traits<InputIt>::difference_type window_length,
OutputIt d_first)
{
using value_type = typename std::iterator_traits<InputIt>::value_type;
auto divide = [&window_length](const value_type& value)
{
return value / window_length;
};
auto iterator = shino::transformer(divide, d_first); //transform_iterator<Functor, Iterator>
shino::sliding_window(first, last, iterator, window_length);
//^^ pass by value
编译器说右值引用版本最终成为 const 左值引用版本。
为了完整起见,这里是 sliding_average
sliding_average(v.begin(), v.end(), window_length, output.begin());
其中v
和output
都是int和double的向量,window_length
是std::size_t
。
当我删除 const 左值版本时,代码编译并正常工作。
此外,这段代码编译时两个构造函数都没有问题:
std::vector<std::string> v{"23", "25", "27"}; //just random numbers
std::vector<int> output(v.size());
auto string_to_int = [](const std::string& x)
{
return std::stoi(x);
};
auto conversion_iterator = shino::transformer(string_to_int, output.begin());
问题:如何解决?
在
auto iterator = shino::transformer(divide, d_first);
您总是要调用函数的 const 左值引用重载。原因是 d_first
是一个命名变量。这意味着它是一个 lvalue
即使它作为右值传递给函数。如果你想让一个命名变量成为右值,你需要使用 std::move
like
auto iterator = shino::transformer(divide, std::move(d_first));
我认为你对lvalues和rvalues的理解不正确。
您没有在您发布的代码中的任何地方使用 rvalue 调用 transform_iterator::transform_iterator
。
auto iterator = shino::transformer(divide, d_first);
// ^^^^^^^
// lvalue
要调用 rvalue 引用 重载,您需要一个 rvalue! std::move
可用于将 d_first
转换为 右值引用 - 示例:
auto iterator = shino::transformer(divide, std::move(d_first));
// ^^^^^^^^^^^^^^^^^^
// rvalue
这同样适用于您在编辑中添加的代码:
shino::sliding_window(first, last, iterator, window_length);
// ^^^^^^^^
// lvalue
你可能想要:
shino::sliding_window(first, last, std::move(iterator), window_length);
// ^^^^^^^^^^^^^^^^^^^
// rvalue
相关问题:
"What are rvalues, lvalues, xvalues, glvalues, and prvalues?"