DeckType (функция) как член класса
-
27-10-2019 - |
Вопрос
У меня есть:
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.