Program A produces a compilation error (as expected) since isfinite doesn't take Foo types.
Program A
#include <cmath>
#include <iostream>
class Foo {};
int main()
{
Foo f;
std::cout << "Foo is finite? " << (std::isfinite(f) ? "yes" : "no") << "\n";
return 0;
}
However, a slight modification (see Program B) allows the program to compile (Visual Studio 2013) and produce the following output.
Program B Visual Studio 2013 Ouput
Foo is finite? yes
Program B
#include <cmath>
#include <iostream>
#include <limits>
class Foo {};
int main()
{
Foo f;
std::cout << "Foo is finite? " << ((!std::numeric_limits<decltype(f)>::has_infinity || std::isfinite(f)) ? "yes" : "no") << "\n";
return 0;
}
It appears that Program B is short circuiting on the logical OR operation and not attempting to compile the rest of the expression. However, this application does not compile using g++ 4.8.3 (g++ -std=c++11 -o main main.cpp). I get the following output.
main.cpp: In function 'int main()':
main.cpp:10:107: error: no matching function for call to 'isfinite(Foo&)'
std::cout << "Foo is finite? " << ((!std::numeric_limits<decltype(f)>::has_infinity || std::isfinite(f)) ? "yes" : "n
^
main.cpp:10:107: note: candidates are:
In file included from main.cpp:1:0:
/usr/include/c++/4.9.2/cmath:582:3: note: constexpr bool std::isfinite(float)
isfinite(float __x)
^
/usr/include/c++/4.9.2/cmath:582:3: note: no known conversion for argument 1 from 'Foo' to 'float'
/usr/include/c++/4.9.2/cmath:586:3: note: constexpr bool std::isfinite(double)
isfinite(double __x)
^
/usr/include/c++/4.9.2/cmath:586:3: note: no known conversion for argument 1 from 'Foo' to 'double'
/usr/include/c++/4.9.2/cmath:590:3: note: constexpr bool std::isfinite(long double)
isfinite(long double __x)
^
/usr/include/c++/4.9.2/cmath:590:3: note: no known conversion for argument 1 from 'Foo' to 'long double'
/usr/include/c++/4.9.2/cmath:596:5: note: template<class _Tp> constexpr typename __gnu_cxx::__enable_if<std::__is_integer<
isfinite(_Tp __x)
^
/usr/include/c++/4.9.2/cmath:596:5: note: template argument deduction/substitution failed:
/usr/include/c++/4.9.2/cmath: In substitution of 'template<class _Tp> constexpr typename __gnu_cxx::__enable_if<std::__is_
main.cpp:10:107: required from here
/usr/include/c++/4.9.2/cmath:596:5: error: no type named '__type' in 'struct __gnu_cxx::__enable_if<false, bool>'
My intuition leads me to believe that the compilation failure is the correct behavior but it is curious that Visual Studio 2013 compiles successfully. My intuition is based on the fact that it is expected that the following code cannot be compiled.
#include <cmath>
#include <iostream>
#include <limits>
struct Foo
{
void doOperation1() {}
void doOperation2() {}
};
struct Bar
{
void doOperationA() {}
void doOperation2() {}
};
template<typename T>
void performOperation(T& t, bool value)
{
if (value)
{
t.doOperation1();
}
else
{
t.doOperation2();
}
}
int main()
{
Foo f;
performOperation(f, true);
performOperation(f, false);
Bar b;
performOperation(b, false); // Fails to compile (as expected)
return 0;
}
Restated Question
Are the logical operators supposed to adhere to short circuit evaluation rules at compile time (i.e., what is the expected compilation behavior of Program B)?
Aucun commentaire:
Enregistrer un commentaire