Можно ли использовать псевдонимы для свободных функций C ?

#c #alias #typedef #using #function-templates

#c #псевдоним #typedef #использование #функция-шаблоны

Вопрос:

У меня есть пространство имен с одной свободной функцией с высоким уровнем шаблонов, такой как:

 namespace a
{
    template<typename T, typename K, typename H>
    void f(T t, K k, std::vector<H> h_vec = {})
    { /* body */ }
}
  

Внутри другого пространства имен для удобства я хотел бы иметь несколько его псевдонимов для множества конкретных применений, таких как:

 namespace b
{
    using my_specific_f = a::f<int,string,char>;
}
  

Это позволило бы мне предоставить лучшее название для функции, поскольку f оно является очень общим в базе кода, над которой я работаю (пожалуйста, имейте в виду, что я привожу здесь только упрощенные примеры, чтобы подчеркнуть суть).
Но, к сожалению, это, по-видимому, запрещено языком.

Итак, со второй попытки я попытался использовать указатель на функцию:

 namespace b
{
    auto my_specific_f = amp;a::f<int,string,char>
}
  

Обычно это сработало бы, но в моем случае это не так, поскольку f имеет один параметр по умолчанию, который, я полагаю, приводит к тому, что функция имеет более одного указателя на функцию (в данном случае два), и может использоваться только версия с тремя параметрами.

На данный момент я просто сдался и просто my_specific_f перенаправил вызов в его теле на f :

 namespace b
{
    void my_specific_f(int i, string s, vector<char> v = {} )
    {
        a::f(i,s,v);
    }
}
  

Но это решение мне не очень нравится, поскольку оно приводит к снижению удобства сопровождения в случае, если f изменит свою подпись, поскольку все функции перенаправления должны быть согласованно адаптированы, и мой первоначальный план состоял в том, чтобы создать больше, чем просто один псевдоним.

Осталось ли что-нибудь, что я мог бы попробовать? Возможно ли это вообще или это будет возможно в какой-нибудь будущей версии стандарта?

Комментарии:

1. using предназначен для типов (псевдонимирование), а не для функций.

2. @KamilCuk да, ясно, что это никогда не будет работать с using . Есть еще идеи?

3. Просто отлично. Теперь я знаю страх.

4. Можете ли вы предоставить MCVE? Ваш второй пример компилируется как есть. gcc.godbolt.org/z/IsoJQR Решение будет зависеть от MCVE.

5. @SergeyA он компилируется, но может использоваться только версия со всеми тремя параметрами, а не версия по умолчанию с двумя.

Ответ №1:

Что вы можете сделать, так это обернуть функцию в общий лямбда-код, чтобы вы могли присвоить ей пользовательское имя. Вы можете сделать это следующим образом

 auto my_really_informative_name = [](autoamp;amp;... args) -> decltype(auto) { 
                                      return f(std::forward<decltype(args)>(args)...);
                                  };
  

Это отлично перенаправляет параметры в f , и если его подпись когда-либо изменится, она все равно будет работать, поскольку лямбда-выражение может принимать любое количество аргументов.

Если вы хотите, чтобы пересылка была идеальной (без уточнения и возвращаемого типа в стиле SFINAE)

 auto my_really_informative_name = [](autoamp;amp;... args) noexcept(noexcept(f(std::forward<decltype(args)>(args)...))) -> decltype(f(std::forward<decltype(args)>(args)...)) { 
                                      return f(std::forward<decltype(args)>(args)...);
                                  };
  

Если вы хотите убедиться, что типы, передаваемые в функцию, относятся к определенному типу, вы можете указать их явно в вызове функции, например

 auto my_really_informative_name = [](autoamp;amp;... args) -> decltype(auto) { 
                                      return f<int, std::string, char>(std::forward<decltype(args)>(args)...);
                                  };
  

Комментарии:

1. С этим решением не было бы способа проверить, что my_really_informative_name на самом деле вызывается с правильными параметрами, которые соответствуют ожиданиям для этого имени. Извините за недоразумение. В моей неправильной первой попытке тот, который пытается использовать using ключевое слово, my_specific_f существует только для параметров int , string и необязательного (по умолчанию пустого) vector<char> .

2. @nyarlathotep108 К ответу добавлено решение.

3. может ли это быть достигнуто также каким-либо образом с ограничением на C 11?

4. @nyarlathotep108 Не как лямбда. Вам пришлось бы написать пользовательский функтор, подобный: coliru.stacked-crooked.com/a/1fa128ddb85f0c57