Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7956 Discussions

Error compiling template function with fmod

mcarey656
Beginner
576 Views

I'm trying to write a simple template function that takes two floating-point values x and y as arguments and returns fmod(x, y):

#include
#include

template
T foo(T x, T y) {
return fmod(x, y);
}

int main(int argc, char* argv[]) {
float x = 4.0, y = 1.0;
double a = 3.5, b = 9.2;

std::cout << "foo(" << x << ", " << y << ") = " << foo(x, y) << std::endl;
std::cout << "foo(" << a << ", " << b << ") = " << foo(a, b) << std::endl;
}

When I try to compile, I get a number of errors like:


1>.\main.cpp(14): error: expected an expression
1> return fmod(x, y);
1> ^
1> detected during instantiation of "T foo(T, T) [with T=float]" at line 21

Any ideas what this error message means? Thanks.

0 Kudos
6 Replies
TimP
Honored Contributor III
576 Views
Quoting - mcarey656

#include
#include

template
T foo(T x, T y) {
return fmod(x, y);
}

int main(int argc, char* argv[]) {
float x = 4.0, y = 1.0;
double a = 3.5, b = 9.2;

std::cout << "foo(" << x << ", " << y << ") = " << foo(x, y) << std::endl;
std::cout << "foo(" << a << ", " << b << ") = " << foo(a, b) << std::endl;
}


1>.main.cpp(14): error: expected an expression
1> return fmod(x, y);
1> ^
1> detected during instantiation of "T foo(T, T) [with T=float]" at line 21


I don't know how much of a problem this is, but you are trying to use a function from C99 in a way which requires C++ specific machinery, so that your use of appears to conflict with C++. So, I would guess you need to make the source more consistent either with C++ or with C. icc supports -std=c99, but icpc does not. In the latest version, icpc -std=c++0x is documented as "enable preliminary support for some C++0x features" but I don't know enough about what those features are.
0 Kudos
mcarey656
Beginner
576 Views
Quoting - tim18
I don't know how much of a problem this is, but you are trying to use a function from C99 in a way which requires C++ specific machinery, so that your use of appears to conflict with C++. So, I would guess you need to make the source more consistent either with C++ or with C. icc supports -std=c99, but icpc does not. In the latest version, icpc -std=c++0x is documented as "enable preliminary support for some C++0x features" but I don't know enough about what those features are.

I tried switching #include to #include and the program compiles. So it does seem that the issue is caused by a C99/C++ clash, although I'm not sure exactly why. I had very similar errors to those mentioned in this post, which is just added confirmation.

So my next question is, how can I use the functionality from without actually including it? I am on Windows and MSVC does not provide functions like fmod and copysign...I noticed that does. What kind of issues could I expect by replacing all instances of #include with #include in an existing (large) project?

Also, in the fmod function is overloaded for float, double, and long double types, but in , you have to use one of fmod, fmodl, or fmodf. How could this work in a template function where I don't know my parameter type in advance? Thanks.

0 Kudos
TimP
Honored Contributor III
576 Views
has no advantage in ability to postpone a choice. It will choose fmod, or fmodf, according to the data types, at compile time. So I don't see that it's any different in effect from C++ overloading. As far as I can see, the VC9 libcmt and math.h have fmod and fmodf, copysign() and copysignf(), and those choices should be available whether you do it in C++ or C99. So I guess just gets in your way here. There is not actually any fmodl, but there is machinery to turn fmodl into fmod, regardless of the arrival route.
C99 doesn't understand C++ syntax, such as any usage of or such for data type selection.
ICL doesn't do much in the way of adding functions, it simply uses those provided by VC, so you don't get library support when you set /Qlong-double in ICL.
0 Kudos
Maxym_D_Intel
Employee
576 Views
MSVC does provide functions like fmod - just see http://msdn.microsoft.com/en-us/library/20dckbeh(VS.71).aspx abd then "Requirements" or simply search MSDN for fmod.


the same for copysign
http://msdn.microsoft.com/en-us/library/aa246720.aspx

#include works good for your code

0 Kudos
mcarey656
Beginner
576 Views
MSVC does provide functions like fmod - just see http://msdn.microsoft.com/en-us/library/20dckbeh(VS.71).aspx abd then "Requirements" or simply search MSDN for fmod.


the same for copysign
http://msdn.microsoft.com/en-us/library/aa246720.aspx

#include works good for your code

Wow you're right, I can't believe I missed that...however, I also need erf(), which MSVC doesn't seem to provide (I hope I'm right about this one, I actually checked this time). Which leaves me with the same issue as before. Tim's answer clarified why I can't use , so would be a viable alternative? If I try to include , I get the following error:

catastrophic error: #error directive: " is incompatible with system !"

0 Kudos
TimP
Honored Contributor III
576 Views
Quoting - mcarey656

Wow you're right, I can't believe I missed that...however, I also need erf(), which MSVC doesn't seem to provide (I hope I'm right about this one, I actually checked this time). Which leaves me with the same issue as before. Tim's answer clarified why I can't use , so would be a viable alternative? If I try to include , I get the following error:

catastrophic error: #error directive: " is incompatible with system !"


Agreed, the documentation is confusing on this point. Apparently, is intended as a full replacement for VC which is optional for ICL, and includes more functionality, such as erf().
ICL links againstits ownlibm.h; the long double functions are hidden (replaced by double) unless we set /Qlong-double /Qpc80 and use . "Microsoft compatibility" includes allowing all long double to be replaced by double and not using any of these options. I hope I didn't misread between the lines.
As the doc on Qlong-double says, there is no printf support for 80-bit long double in any Intel or Microsoft Windows library.
0 Kudos
Reply