我写了这样一个静态类型转换的模板函数作为练习:
template<typename cT, typename T>
inline constexpr cT sCast(T carg) {
return static_cast<cT>(carg);
}
字符串
我只是不想一直输入static_cast<someT>(some_obj)
,所以我挑战自己,用一个更短的名字写我自己的模板函数。然而,我知道我可以用一行代码做一些更容易的事情:
#define sCast static_cast
...
sCast<someT>(some_obj);
型
但正如我所说,我想设计一个函数模板只是为了练习。
现在我的问题是这个函数模板是否尽可能高效?如果不是,如何才能更好?模板函数是否满足RVO优化的条件?或者我只是一个完美主义者,这样的想法是浪费时间?
3条答案
按热度按时间pgpifvop1#
该模板不如仅使用
static_cast
有效。原因是函数必须被显式地推送到堆栈上,并且它的参数必须在之后被清理。大多数编译器会内联它(==>就好像你写了static_cast
而不是上面的函数),但是如果你的编译器选择不内联它,它会影响你的性能(即使只是轻微的,而且不太可能有人会注意到)。x759pob22#
您的模板根本不能替代
static_cast
。考虑涉及引用的情况。如果不显式指定第二个参数,最终将无法推导引用:
字符串
输出量:
型
正如你所看到的,
sCast
做了一个额外的副本,这个副本甚至在下一个表达式之前被销毁,这很容易导致未定义的行为。使用转发引用可以解决这个问题,但在某些情况下仍然会得到不同的语义:
型
具有不同语义的代码:
型
产出
型
我的建议是继续使用
static_cast
。这也会帮助其他人阅读你的代码;他们几乎肯定熟悉static_cast
,但他们可能需要查找sCast
,至少在第一次遇到该函数时是这样。另外,IDE将突出显示static_cast
,与函数模板调用不同。总的来说,我不认为不惜一切代价缩短代码是一个好主意。如果通过多输入几个字符来增加可读性,那么这是值得的。如果你不想为打字而烦恼,几乎每个文本编辑器都有搜索和替换功能。
vfh0ocws3#
在C++14中:强制转换为非引用类型将创建一个副本。该副本受制于RVO,但static_cast永远不会有额外的临时复制/移动。举例来说:
字符串
这个问题在C++17中不存在,因为省略该移动是强制性的。
static_cast
也有特殊的措辞。生存期扩展可以通过静态强制转换来完成,如果强制转换的类型不依赖于类型,则它们不依赖于类型。型
这不能用函数模板来模拟。
你的函数也没有正确处理右值,总是复制它的参数。例如:
型
这可以通过完美转发来解决:
型
您的函数对SFINAE不友好。在重载解析期间,它将声明始终可调用。举例来说:
型
您可以通过在
static_cast
失败时将其设置为替换失败来修复此问题。最简单的是这样的:型
您的函数模板不能正确接受纯右值。上面的“完美转发”将纯右值更改为x值。举例来说:
型