decltype (функция) как член класса - PullRequest
6 голосов
/ 17 февраля 2012

у меня есть:

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)'

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

Ответы [ 3 ]

5 голосов
/ 17 февраля 2012

Кажется, вы хотите «скопировать» подпись другой функции, чтобы создать функцию с такой же подписью.Поскольку 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.Вы все еще должны определить это.А поскольку нет синтаксиса для его определения с использованием decltype, вам явно нужно записать его как

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

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

2 голосов
/ 17 февраля 2012

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

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

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

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

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

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

0 голосов
/ 17 февраля 2012

Это должно работать.Я просто использовал его здесь, чтобы запечатлеть то, что собирался дать мне 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.

...