使用Boost Locale / ICU,我为使用Mingw时输出非ASCII字符到Windows控制台(cmd)的问题创建了一个解决方案。
现在,我决定使用Visual Studio,只是发现使用std::locale::global(std::local(""))
将导致cmd上的正确非ASCII输出,因此不需要我的解决方案。
目前,VS上的代码#error
,但我希望它更具可移植性,即在VS和Mingw上使用该代码,但在VS上无效。
显而易见的解决方案是预处理器,就像这样(简化,我省略了像do {} while(0)
这样的东西):
#if defined(_MSC_VER)
#define SOME_HOPEFULLY_UNIQUE_PREFIX_CONVERT_OUTPUT(x) x
#else
#define SOME_HOPEFULLY_UNIQUE_PREFIX_CONVERT_OUTPUT(x) ConvertOuput(x)
#endif
然后我想知道我是否可以使用刚刚返回其参数的函数模板获得相同的结果。像这样:
template <typename T>
T ConvertOutput(T t)
{
return t;
}
使用char*
的简单测试符合预期(在MSVC社区2015上的x64版本配置),对ConvertOutput()
的调用被忽略了:
lea rdx,[string "teste" (013F79761Ch)]
mov rcx,qword ptr [__imp_std::cout (013F797178h)]
call std::operator<<<std::char_traits<char> > (013F791690h)
mov dl,0Ah
mov rcx,rax
call std::operator<<<std::char_traits<char> > (013F791870h)
但使用std::string
进行同样的简单测试表明,虽然我们获得了RVO,但仍有一个临时构建和ConvertOutput()
的调用:
124: std::string b1{"teste2"};
mov qword ptr [rsp+88h],0Fh
mov qword ptr [rsp+80h],0
mov byte ptr [b1],0
mov r8d,6
lea rdx,[string "teste2" (013F127624h)]
lea rcx,[b1]
call std::basic_string<char,std::char_traits<char>,
std::allocator<char> >::assign (013F1210C0h)
nop
125: auto b2 = ConvertOutput(b1);
mov qword ptr [rsp+38h],0Fh
mov qword ptr [rsp+30h],0
mov byte ptr [rsp+20h],0
or r9,0FFFFFFFFFFFFFFFFh
xor r8d,r8d
lea rdx,[b1]
lea rcx,[rsp+20h]
call std::basic_string<char,std::char_traits<char>,
std::allocator<char> >::assign (013F1211F0h)
lea rdx,[rsp+20h]
lea rcx,[b2]
call ConvertOutput<std::basic_string<char,std::char_traits<char>,
std::allocator<char> > > (013F124090h)
nop
我有一些希望编译器,知道所有ConvertOuput()
所做的都是返回它的参数,也可以在这里忽略它。我意识到这可能是不明智的,因为任意T
的拷贝ctor可能有一些所需的副作用(?),但是由于实例化发生在std::string
,我希望编译器有更多的摆动有std
个班级的房间。
ConvertOutput()
的专精std::string
给出了类似的结果 - 如果ConvertOutput()
接受参考,则临时消失,但呼叫仍在那里。
作为最后的尝试,我像这样重载了ConvertOutput()
:
template <typename CharT>
CharT const* ConvertOutput(std::basic_string<CharT> const &t)
{
cout << "Ref: " << t << '\n';
return t.c_str();
}
我终于得到了我期望的行为,包括ConvertOutput()
电话的省略/内联:
132: std::string b1{"teste2"};
mov qword ptr [rsp+40h],0Fh
mov qword ptr [rsp+38h],0
mov byte ptr [b1],0
mov r8d,6
lea rdx,[string "teste2" (013F697624h)]
lea rcx,[b1]
call std::basic_string<char,std::char_traits<char>,
std::allocator<char> >::assign (013F6910C0h)
nop
133: auto b2 = ConvertOutput(b1);
lea rdx,[string "Ref: " (013F697730h)]
mov rcx,qword ptr [__imp_std::cout (013F697178h)]
call std::operator<<<std::char_traits<char> > (013F691690h)
mov rcx,rax
lea rdx,[b1]
call std::operator<<<char,std::char_traits<char>,
std::allocator<char> > (013F691A30h)
mov rcx,rax
mov dl,0Ah
call std::operator<<<std::char_traits<char> > (013F691870h)
lea rdx,[b1]
cmp qword ptr [rsp+40h],10h
cmovae rdx,qword ptr [b1]
我看不到与模板的预处理器宏相同的效果,至少没有相当多的警告。
我错了吗?是否有一种方法(简单或其他方式)使用模板实现此目的,而不对每种使用的类型进行重载/专门化?
答案 0 :(得分:4)
std::forward
:
template <typename T>
T&& ConvertOutput(T&& t)
{
return std::forward<T>(t);
}