Рассмотрим следующий шаблон функции:Автоматическая оценка стратегии Выбор в C++
template<typename T> void Foo(T)
{
// ...
}
Pass по значению семантики имеют смысл, если T
случается целочисленный тип, или, по крайней мере, тип, который дешев, чтобы скопировать. С другой стороны, использование семантики pass-by- [const] -reference имеет смысл, если T
оказывается дорогостоящим типом для копирования.
Предположим на секунду, что вы пишете библиотеку. В идеале, как разработчик библиотеки, ваша задача - предоставить вашим потребителям чистый 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 является «да» - как обрабатывается случай неклассического шаблона?
- Есть ли явные подводные камни, которые я не вижу с чем-то подобным?
- Наконец, это даже разумная вещь?
* Не профилированный. ;)
собирался упомянуть http://www.boost.org/doc/libs/1_43_0/doc/html/ref.html – 5ound
@ 5ound: Также полезно, спасибо! – chrosph