По сути, то, что вы хотите сделать, невозможно в текущем C ++. Для любого количества функций, которые вы хотите обернуть, вам нужно перегрузить на
const reference
non-const reference
Но тогда это все еще не идеально пересылка (некоторые крайние случаи все еще стоят), но это должно работать разумно хорошо. Если вы ограничиваете себя постоянными ссылками, вы можете пойти с этим (не проверено):
template<class Function>
class Timer {
typedef typename boost::function_types
::result_type<Function>::type return_type;
public:
Timer(Function fct)
: fct_(fct) {}
// macro generating one overload
#define FN(Z, N, D) \
BOOST_PP_EXPR_IF(N, template<BOOST_PP_ENUM_PARAMS(N, typename T)>) \
return_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, T, const& t)) { \
/* some stuff here */ \
fct_(ENUM_PARAMS(N, t)); \
}
// generate overloads for up to 10 parameters
BOOST_PP_REPEAT(10, FN, ~)
#undef FN
long GetElapsedTime() { return elapsed_time_; }
private:
// void() -> void(*)()
typename boost::decay<Function>::type fct_;
long elapsed_time_;
};
Обратите внимание, что для возвращаемого типа вы можете использовать библиотеку типов функций boost. Тогда
Timer<void(int)> t(&foo);
t(10);
Вы также можете перегрузить, используя параметры с чистыми значениями, а затем, если вы хотите передать что-либо по ссылке, используйте boost::ref
. На самом деле это довольно распространенный метод, особенно когда такие параметры будут сохранены (этот метод также используется для boost::bind
):
// if you want to have reference parameters:
void bar(int &i) { i = 10; }
Timer<void(int&)> f(&bar);
int a;
f(boost::ref(a));
assert(a == 10);
Или вы можете пойти и добавить эти перегрузки для константной и неконстантной версий, как описано выше. Посмотрите в Boost.Preprocessor , как написать правильные макросы.
Вы должны знать, что все это станет более сложным, если вы хотите иметь возможность передавать произвольные вызываемые объекты (не только функции), поскольку тогда вам понадобится способ получить их тип результата (это не так просто) , C ++ 1x упростит такие вещи.