gpt4 book ai didi

返回参数的函数模板的 C++ 编译器优化

转载 作者:行者123 更新时间:2023-11-30 01:44:43 26 4
gpt4 key购买 nike

使用 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 Community 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 的复制构造函数可能会产生一些预期的副作用(?),但由于实例化发生在 std::string ,我希望编译器在 std 类中有更多的回旋余地。

std::string 专门化 ConvertOutput() 得到了类似的结果 - 如果 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]

我看不出有什么方法可以用模板实现与预处理器宏相同的效果,至少在没有大量警告的情况下是这样。

我错了吗?有没有一种方法(简单或其他方式)可以使用模板实现此目的,而无需为每种使用的类型重载/专门化?

最佳答案

std::forward 怎么样:

template <typename T>
T&& ConvertOutput(T&& t)
{
return std::forward<T>(t);
}

关于返回参数的函数模板的 C++ 编译器优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35654712/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com