Вопрос

У меня есть:

int foo(int x) { return x+1; }

struct Bar {
  decltype(foo) operator();
};

int main() {
  Bar bar;
  printf("%d\n",bar(6));
}

что приводит к слегка поразительному сообщению об ошибке компилятора (G ++ 4.6.1):

error: declaration of 'operator()' as non-function

При изменении имени участника на

  decltype(foo) blubb;

и использование его приводит к ошибке линкера:

undefined reference to `Bar::blubb(int)'

Это ожидаемое поведение?

Это было полезно?

Решение

Кажется, что вы хотите «скопировать» подпись другой функции, чтобы создать функцию с той же подписью. С decltype(foo) действительно тип функции (а не указатель на эту функцию, которая была бы decltype(&foo) и приведет к объявлению указателя), вы можете использовать ее для объявления функции с той же подписью, что и другая функция.

Как указано ошибкой линкера:

undefined reference to `Bar::blubb(int)'

Это уже прекрасно будет работать с вашим компилятором. Однако кажется, что GCC еще не полностью реализовал эту часть стандарта, так как он не примет синтаксис для того же самого с оператором вызова функции. Кланг, кстати. с радостью примет это, и ссылка затем ошибся с

undefined reference to `Bar::operator()(int)'

Ваш вопрос о том, почему эта ошибка линкера существует, указывает на недопонимание того, что на самом деле делает Decltype.

Это просто оценится на тип, а не больше. Определение blubb никоим образом не связан с определением foo. Анкет Это может быть яснее при написании этого как

typedef decltype(foo) x; 
x blubb;

Теперь вы можете альтернативно Typedef X, чтобы быть явно типом функции, который никоим образом не изменит то, что является Blubb. Вам все еще нужно определить это. И поскольку нет никакого синтаксиса для определения его с помощью DeckType, вам явно приходится написать его как

int Bar::operator()(int) {
...
}

что, вероятно, и, к сожалению, победить цель/выгоду от использования Decltype для объявления, поскольку это не позволит вам автоматически «копировать» подпись.

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

Это дикое предположение, основанное на наблюдении за использованием вашего Printf здесь:

printf("%d\n",bar(6));

Это позволяет мне предположить, что вы действительно хотите Возврат тип функции, а не типа функции. Если так, то вы используете decltype неправильный. Вы получаете возвратный тип функции, «моделируя» использование функции, т.е.

decltype(foo(0)) operator() (int);

Должен быть правильным для вас. В противном случае, если это не было ваше внимание, вы катаетесь на коньках на тонком льду, давая тип функции (а не возвращаемый тип функции) %d Спецификатор.

Как правило, значение decltype является: decltype(@) дает статический тип выражения @.

Это должно работать. Я просто использовал его здесь, чтобы запечатлеть то, что GobbledyGook std::bind собирался дать мне:

class RiceFadingModel::Impl
{
public:
  Impl(double K, double A)
  : //...
    _M_re{system_now()},
    _M_rd{_M_nu, _M_sigma},
    _M_gen{std::bind(_M_rd, _M_re)}
  { }


private:

//...

  std::default_random_engine _M_re;
  ///  The underlying Rice distribution.
  __gnu_cxx::__rice_distribution<double> _M_rd;
  ///  The variate generator built from the pseudo-random number engine and the Rice distribution.
  decltype(std::bind(_M_rd, _M_re)) _M_gen;
};

Это работает как очарование на GCC-4.7. Теперь, когда я думаю об этом, я тоже построил его на Mingw с GCC-4.5.

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