考虑以下函数模板:
template<typename T> void Foo(T)
{
// ...
}
T
如果碰巧是整数类型,或者至少是复制成本低的类型,则按值传递语义是有意义的。另一方面,如果T
碰巧是要复制的昂贵类型,则使用 pass-by-[const]-reference 语义更有意义。
让我们假设您正在编写一个库。理想情况下,作为库实现者,您的工作是为您的消费者提供尽可能通用和高效的干净 API。那么,你如何提供一个通用接口来满足这两种类型的参数传递策略呢?
这是我第一次尝试让它工作:
#include <boost/type_traits.hpp>
template<typename T> struct DefaultCondition
{
enum {value = boost::is_integral<T>::value /* && <other trait(s)> */};
};
template< typename T, class Condition = DefaultCondition<T> > class Select
{
template<bool PassByValue = Condition::value, class Dummy = void> struct Resolve
{
typedef T type;
};
template<class Dummy> struct Resolve<false, Dummy>
{
typedef const T& type;
};
public: typedef typename Resolve<>::type type;
};
典型用法:
template<typename T> class EnterpriseyObject
{
typedef typename Select<T>::type type;
public: explicit EnterpriseyObject(type)
{
// ...
}
};
struct CustomType {};
void Usage()
{
EnterpriseyObject<int>(0); // Pass-by-value.
(EnterpriseyObject<CustomType>(CustomType())); // Pass-by-const-reference.
}
当然,这间接破坏了非类模板的隐式模板参数推导:
template<typename T> void Foo(typename Select<T>::type)
{
// ...
}
void Usage()
{
Foo(0); // Incomplete.
Foo<int>(0); // Fine.
}
这可以通过Boost.Typeof
库和宏来“修复”,例如WinAPI
:
#define Foo(Arg) ::Foo<BOOST_TYPEOF((Arg))>((Arg))
虽然这只是一个准便携式黑客。
如您所见,我的一般方法并非对所有情况都真正令人满意。
作为一名业余程序员,我既没有实际经验,也无法获得生产质量的代码以供参考。我也意识到这似乎是过早优化的一个糟糕案例,但我真的对几件事感兴趣:
- 您过去是否或曾经使用过这种类型的优化*?
- (或任何其他公共)库是否
Boost
已经提供了类似的功能? - 如果#1 或#2 的答案是“是”——如何处理非类模板案例?
- 有没有我没有看到这样的明显陷阱?
- 最后,这甚至是明智的做法吗?
* 没有描述。;)