我正在编写一个基本的类模板。它的参数采用两种参数类型。类的思想是将一种类型作为const ref,另一种类型作为ref。类的功能是将类型A转换为B类型,创建的对象最终将是b。我希望perfect-forwarding或move semantics是这个类模板的有效部分。
现在,这里是我的当前类,它只包含基本类型,但计划通过使用各种构造将其扩展到任何2种类型。
#ifndef CONVERTER_H
#define CONVERTER_H
#include <utility>
template<class From, class To>
class Converter {
private:
From in_;
To out_;
public:
// Would like for From in to be a const (non modifiable) object
// passed in by perfect forwarding or move semantics and for
// To out to be returned by reference with perfect forwarding
// or move semantics. Possible Constructor Declarations - Definitions
// Using std::move
Converter( From&& in, To&& out ) :
in_{ std::move( in ) },
out_{ std::move( out ) }
{
// Code to convert in to out
}
// Or using std::forward
Converter( From&& in, To&& out ) :
in_{ std::forward<From>( in ) },
out_{ std::forward<To>( out ) } {
// Code to convert in to out.
}
// Pseudo operator()...
To operator()() {
return out_;
}
};
#endif // !CONVERTER_H无论以哪种方式,我用std::move或std::forward来声明上面的构造函数,这个类都是自己编译的。现在,当我包括这个,并尝试实例化一个对象以上调用它的构造函数.如果我这么做:
int i = 10;
float f = 0;
Converter<int, float> converter( i, f );在这两种情况下,Visual 2017都会出现编译器错误。
1>------ Build started: Project: ExceptionManager, Configuration: Debug Win32 ------
1>main.cpp
1>c:\users\skilz80\documents\visual studio 2017\projects\exceptionmanager\exceptionmanager\main.cpp(54): error C2664: 'Converter<unsigned int,float>::Converter(Converter<unsigned int,float> &&)': cannot convert argument 1 from 'unsigned int' to 'unsigned int &&'
1>c:\users\skilz80\documents\visual studio 2017\projects\exceptionmanager\exceptionmanager\main.cpp(54): note: You cannot bind an lvalue to an rvalue reference
1>Done building project "ExceptionManager.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========这是可以理解的{can't bind lvaule to rvalue ref}。
但是,如果我尝试像这样使用构造函数:
int i = 10;
float f = 0;
Converter<int,float> converter( std::move( i ), std::move( f ) );
// Or
Converter<int,float> converter( std::forward<int>( i ), std::forward<float>( f ) );它编译和构建,不管std::move(...)或std::forward<T>(...)是否在类中使用。
据我更好的理解,很明显,
std::move(...)&std::forward<T>(...)几乎是可以互换的,并且做同样的事情,除了std::forward<T>(...)有额外的演员。
现在,由于我只展示了基本类型,所以使用std::move似乎更合理,但是我最终可能希望使用更复杂的类型,因此我希望提前设计它,考虑到这一点,所以我倾向于使用std::forward<T>来实现完美的转发。
说到这里,为了完成这门课,有三个问题结合在一起。
std::move或std::forward,为什么在实例化模板类对象时必须再次使用它们;这难道不被认为是多余的吗?如果是这样的话,构造函数的外观将如何,以便用户在调用此构造函数时不必使用std::move()或std::forward<T>()?A转换为B的最普遍和最安全的方法是什么?operator()()的内容,对于上面已经提到的内容,它会是什么样子呢?为了完成以上三个耦合问题的处理,我最后的想法是,在设计过程的某一时刻,我曾经考虑过使用std::any及其相关功能作为其实现过程的一个可能部分。我不知道在这个上下文中是否可以使用std::any,如果可以,如何使用?
编辑
以下是这个类的几种可能的未来用途:
vector<int> vecFrom{1,2,3, ...};
set<int> setTo;
Converter<vector<int>, set<int>> converter( vecFrom, setTo );或者在扩张之后。
vector<int> vecIntFrom{1,2,3, ...};
vector<string> vecStringFrom{ "a", "b", "c", ... };
map<int,string> mapTo;
Converter<vector<int>, vector<string>, map<int,string> converter( vecIntFrom, vecStringFrom, mapTo );发布于 2018-03-20 01:06:15
这里有许多问题,我似乎不太清楚地回答,但有一个问题很突出:
“std::move和std::forward有什么区别?”
移动用于将lvalue引用转换为rvalue引用,通常用于将一个lvalue所持有的资源转移到另一个。
forward用于区分lvalue和rvalue引用,通常是在将rvalue引用类型的参数推断为lvalue的情况下。
结果:如果要根据传递时对象的引用类型进行分支,请使用std::forward。如果您只想通过转换为rvalue来窃取lvalue的资源,请使用std::move。
有关更多细节,我发现以下内容很有帮助:01.html
https://stackoverflow.com/questions/48454577
复制相似问题