我有一个结构模板,它有两种类型(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也不合法:如果您的副本构造函数具有副作用或编译器无法证明它没有副作用(如果复制构造函数不常见),它将被调用.