Добрый день.
Пишу простой код:
template<float(*math_fun)(float)> float run_math_fun(float arg) {
float ret = (*math_fun)(arg);
return ret;
}
float ddd() {
float a = 10.0;
return run_math_fun<&fabs>(a);
}
Транслятор VS2017 нормально транслирует этот код.
Транслятор GCC (из состава wxDev-C++) транслировать этот код отказывается и выдает следующую диагностику:
In function 'float ob_charspace::ddd()'::
no matching function for call to 'run_math_fun(float&)'
candidate is:
template<float (* math_fun)(float)> float ob_charspace::run_math_fun(float)
[Build Error] [obj/ob7.o] Error 1
При этом саму функцию fabs транслятор GCC видит, понимает и, если вызвать fabs явно, то трансляция проходит нормально.
Вопрос:
Спасибо.
fabs без namespace'а — это Си'шный вариант. В C++ надо сделать одно из трёх:
// 1; будет ли работать зависит от деталей реализации libm
#include <math.h>
// 2
#include <cmath>
using namespace std;
// 3
#include <cmath>
// ...
return run_math_fun<&std::fabs>(a);
Последнее ИМХО предпочтительнее.
Согласно тому, что вы написали в комментариях, ради доступа к fabs вы включаете <math.h>. Однако простой эксперимент показывает, что при включении только <math.h> ваш код не компилируется ни в VS2017, ни в GCC, по одной и той же причине - не существует функции fabs, которая принимала бы аргумент типа float и возвращала бы результат типа float. Такой код и не должен компилироваться. Так что никакой несовместимости между компиляторами тут нет.
Для компилируемости вашего кода нужно включение <cmath>. Очевидно, что у вас в случае с VS2017 этот заголовочный файл оказался включенным тоже: он оказался неявно/случайно включенным через посредство каких-то других заголовочных файлов стандартной библиотеки С++. Это случайное включение <cmath> и приводило к компилируемости кода. В GCC это случайное включение не имеет места, вследствие чего в GCC код не компилируется.
Также следует заметить, что компоненты стандартной библиотеки в заголовочном файле <cmath> должны быть объявлены в пространстве имен std. Однако не оговаривается, каким образом это достигается: либо прямым объявлением этих имен в std, либо объявлением этих имен в глобальном пространстве имен и последующим переобъявлением их в std при помощи using-объявлений.
Компоненты стандартной библиотеки в заголовочном файле <math.h> должно быть объявлены в глобальном пространстве имен. Но совершенно симметричным образом этот заголовочный файл может внутреннее сначала объявлять эти имена в пространстве имен std, а затем переобъявлять их в глобальном пространстве имен при помощи using-объявлений.
Это значит, что доступность этих имен в "альтернативном" пространстве имен может варьироваться от реализации к реализации. Включая <cmath> вы гарантированно получите имена в в пространстве имен std, и при этом можете получить (а можете и не получить) эти имена в глобальном пространстве имен. С <math.h> ситуация обратная.
То есть подобный эффект может возникать и по таким причинам. Но эксперимент показывает, что в данном случае дело просто в неявном включении <cmath>.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей