Вопрос

Можно ли объявить функцию bar чтобы иметь ту же сигнатуру, что и функция foo?

int foo(int a)
{
    return 0; 
}

decltype(foo) bar
{
    return 1;
} //imaginary syntax
Это было полезно?

Решение

Я думаю, что то же самое относится и к определениям типов и псевдонимам:Вы можете использовать decltype к объявлять функция, но не для ее определения:

int foo();

decltype(foo) bar;

int foo()
{
    return bar();
}

int bar() { return 0; }

принимается clang++3.5 и g++4.8.1


[dcl.fct.def.general]/2 запрещает (грамматически) определение функции без круглых скобок:

Декларатор в определении функции должен иметь вид

       D1 ( параметр-объявление-предложение ) резюме-квалификатор-seqвыбирать ссылка-квалификаторвыбирать исключение-спецификациявыбирать атрибут-спецификатор-seqвыбирать завершающий-возвращаемый-типвыбирать

как описано в разделе 8.3.5.

Другие советы

Вы можете использовать шаблоны variadic для определения функции, которая имеет ту же сигнатуру, что и какой-нибудь функция:

#include <iostream>

int foo(char const *blah) { return 0; }

template<typename... Args>
auto bar(Args ... args) -> decltype(foo(args...))
{
    return 1; 
}

int main() {
    std::cout << foo("test") << std::endl;
    std::cout << bar("test") << std::endl;
    return 0;
}

Это также можно было бы немного изменить, чтобы передать "foo" в качестве первого аргумента шаблона, чтобы вы могли использовать один и тот же "bar" со многими разными "foo".:

template<typename Func, typename... Args>
auto bar(Func f, Args ... args) -> decltype(f(args...))
{
    return 1; 
}

int baz(double d) { return 3; }

int main() {
    std::cout << bar(&foo, "test") << std::endl;
    std::cout << bar(&baz, 1.2) << std::endl;
    return 0;
}

Первое, что приходит на ум, это то, что вам нужно назвать параметры, так что нет, вы не можете.

Тип foo - это:

int(int)

таким образом, любой воображаемый синтаксис объявления, подобный:

decltype(foo) bar { //imaginary syntax
  // can't access parameter
  return 1;
}

возникнет проблема, которая bar не удается получить доступ к параметрам.

Так что лучшее, что вы можете сделать, - это то, что предлагает @dyp.

Еще одна вещь, которую вы могли бы сделать, - это проверить, имеют ли две функции одинаковую сигнатуру:

static_assert(std::is_same<decltype(foo), decltype(bar)>::value, "Invalid bar signature");

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

#include <stdio.h>
int sf(int, float, double, bool) {}
template <typename RV, typename... args>
RV func(args... as) {
  printf("%d %f %f %d\n", as...);
  return sf(as...);
}
template <typename RV, typename... args>
RV(*generateFunc(RV(*)(args...)))(args...) {
  return &func<RV, args...>;
}

int main() {
  decltype(sf) *f = generateFunc(sf);
  f(42, 1.0f, 12.0, true);
}

Это генерирует функцию, соответствующую сигнатуре sf, а затем перенаправляет вызов на нее.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top