(Я ограничу этот вопрос C ++ 11, поскольку я считаю, что в C ++ 98 нет общего способа сделать это).
Предполагается, что у меня сложный (с точки зрения подписи) набор шаблон функции и / или перегруженные функции, и я хочу использовать эти функции точно так же, но используя другое имя (то есть псевдоним).
Например:
template<class A, class B, class C>
D fun(A a, B& b, C&& c){ ... }
template<class E, class F>
G fun(H<E> he, F& f){ ... }
... many other versions of fun
Теперь предположим, что я хочу переименовать (или же псевдоним, или же вперед чтобы быть более точным) эти функции, все сразу (т.е. иметь возможность использовать другое имя для той же функции, не переписывая ее). Так что в других частях кода я могу использовать его с другим именем и без изменения приведенного выше кода.
Это правильный способ переименовать (Псевдоним / вперед) fun
в gun
?
template<typename... Args>
inline auto gun(Args&&... args)->decltype(fun(std::forward<Args>(args)...)){
return fun(std::forward<Args>(args)...);
}
template<class A, class B, class C, class = std::enable_if< ... >::type>
), будут decltype
передать СФИНА во всех случаях?double& fun(double& x){return x;}
).Разъяснение: gun
никогда не будет именно так fun
, поскольку экземпляры будут иметь разные адреса, но я ищу переименование с точки зрения общего кодирования.
Комментарий: я нахожу странным, что почти все можно переименовывать / пересылать, пространства имен, типы (typedef
) и типы шаблонов using typedef
, но не функции (или в этом отношении функции-члены).
РЕДАКТИРОВАТЬ: Для полноты, и так как кажется, что это способ сделать это, я добавил макрос для определения псевдонимов функций:
#define ALIAS_FUNCTION(OriginalnamE, AliasnamE) \
template <typename... Args> \
inline auto AliasnamE(Args&&... args) -> decltype(OriginalnamE(std::forward<Args>(args)...)) { \
return OriginalnamE(std::forward<Args>(args)...); \
}
и затем вы используете это так:
namespace NS1{namepsace NS2{
ALIAS_FUNCTION(NSA::fun, gun); // second argument (target name can't have namespace)
}}
Это действительно общее?
Да.
Это самый простой способ?
Да (печально)
Это оптимальный путь? (например, может быть встроенным, без лишних копий)
Да.
Что, если исходная функция имела некоторые функции SFINAE? (например.
template<class A, class B, class C, class = std::enable_if< ... >::type>
), будет ли decltype передавать SFINAE во всех случаях?
Да, если выражение внутри decltype
выдает ошибку (т.е. fun
не существует, возможно, из-за SFINAE на fun
), это вызовет SFINAE для gun
а также, удалив его из набора перегрузки.
Что если исходная функция вернула ссылки? Разве decltype не собирается удалять тип ссылок? (например.
double& fun(double& x){return x;}
).
Нет, с чего бы это?
То же самое можно сказать и о функциях-членах, хотя это должно быть сделано путем изменения класса, я думаю.
Это не вопрос. Что можно сказать о функциях-членах? Все вышеперечисленное относится в равной степени.
Других решений пока нет …