我有一个结构模板,它有两种类型(T和S),在某种程度上使用一个static_cast从一种类型转换为另一种类型.通常情况下,T和S是相同的类型.
一个简化的设置示例:
template <typename T,typename S = T>
struct foo
{
void bar(T val)
{
/* ... */
some_other_function(static_cast<S>(val));
/* ... */
}
};
在S与T相同的情况下,static_cast是否或可以引入额外的开销,还是一个总是被忽略的空操作?
如果它引入了开销,是否有一个简单的模板元编程技巧来执行static_cast只有在需要的时候,还是需要创建一个部分专业化来处理T == S的情况?如果可能,我宁愿避免整个foo模板的部分专业化.
解决方法
是的,它可以.
这是一个例子:
struct A {
A( A const& ) {
std::cout << "expensive copy\n";
}
};
template<typename T>
void noop( T const& ) {}
template <typename T,typename S = T>
void bar(T val)
{
noop(static_cast<S>(val));
}
template <typename T>
void bar2(T val)
{
noop(val);
}
int main() {
std::cout << "start\n";
A a;
std::cout << "bar2\n";
bar2(a); // one expensive copy
std::cout << "bar\n";
bar(a); // two expensive copies
std::cout << "done";
}
基本上,static_cast可以引发一个复制构造函数被调用.
对于某些类型(如int),复制构造函数基本上是空闲的,编译器可以消除它.
对于其他类型,它不能.在这种情况下,copy elision也不合法:如果您的副本构造函数具有副作用或编译器无法证明它没有副作用(如果复制构造函数不常见),它将被调用.