How come that std::greater is no more part of the std namespace in Visual Studio 2012? I now need to include <functional>
I thought STL libraries remained the same across toolsets
How come that std::greater is no more part of the std namespace in Visual Studio 2012?
I'd be very surprised if that were the case.
I now need to include <functional.h>
No, you need to include <functional> since that's the header that defines all the standard function objects, including greater.
I thought STL libraries remained the same across toolsets
They should be. But headers are allowed to include other headers, so sometimes you'll find that something is available even if you haven't included the correct header. But you can't rely on that, as you've found here. Always include all the headers you need for the things you use.
The following example, taken from here, compiles and executes correctly for me in Visual Studio 2012:
// greater example
#include <iostream> // std::cout
#include <functional> // std::greater
#include <algorithm> // std::sort
int main () {
int numbers[]={20,40,50,10,30};
std::sort (numbers, numbers+5, std::greater<int>());
for (int i=0; i<5; i++)
std::cout << numbers[i] << ' ';
std::cout << '\n';
return 0;
}
Output:
50 40 30 20 10
As per the question comments and the example above, you need to include <functional>, not <functional.h>.
Related
I was trying to use shared pointers in CUDA by using NVIDIA's version of the C++ standard library. So tried to include <cuda/std/detail/libcxx/include/memory>. I got some errors. One of them includes cannot open source file with <__config> and <__functional_base>. Those files were clearly in the directory. It's like visual studios acts like those files don't exist even though they do. Another error I get is linkage specification is incompatible with previous "" with <cmath>.
I did little digging. I found out that cannot open source file is apparent with every non-header file that starts with _ in cuda/std/detail/libcxx/include/. It is like Visual Studio somehow acts like those files don't exist despite being clearly located in the additional include directories. Furthermore, when I type cuda/std/detail/libcxx/include/, IntelliSense won't find these files. If I can get visual studio to recognize those files, I can properly include any files in NVIDIA's version of standard library.
The first thing to understand is that CUDA doesn't have a C++ standard library. What you are referring to is the libcu++, which is an extremely bare bones heterogenous reimplementation of a tiny subset of what is defined in the C++ standard library. You can use whatever is defined in libcu++ (and that is not much, it is a very incomplete implementation) as follows:
Prepend the local path cuda/std/ to whatever standard library header you are using to substitute the import from the native host C++ standard library to libcu++
Change the namespace from std to cuda::std
compile using nvcc
As a simple example:
$ cat atomics.cpp
#include <iostream> // std::cout
#include <cuda/std/atomic> // cuda::std::atomic, cuda::std::atomic_flag, ATOMIC_FLAG_INIT
#include <thread> // std::thread, std::this_thread::yield
#include <vector> // std::vector
cuda::std::atomic<bool> ready (false);
cuda::std::atomic_flag winner = ATOMIC_FLAG_INIT;
void count1m (int id) {
while (!ready) { std::this_thread::yield(); } // wait for the ready signal
for (volatile int i=0; i<1000000; ++i) {} // go!, count to 1 million
if (!winner.test_and_set()) { std::cout << "thread #" << id << " won!\n"; }
};
int main ()
{
std::vector<std::thread> threads;
std::cout << "spawning 10 threads that count to 1 million...\n";
for (int i=1; i<=10; ++i) threads.push_back(std::thread(count1m,i));
ready = true;
for (auto& th : threads) th.join();
return 0;
}
$ nvcc -std=c++11 -o atomics atomics.cpp -lpthread
$ ./atomics
spawning 10 threads that count to 1 million...
thread #6 won!
Note that as per the documentation, there are presently (CUDA 11.2) only implementations of:
<atomic>
<latch>
<barrier>
<semaphore>
<chrono>
<cfloat>
<ratio>
<climits>
<cstdint>
<type_traits>
<tuple>
<functional>
<utility>
<version>
<cassert>
<cstddef>
with complex support coming in the next CUDA release from the looks of things.
You mentioned shared pointers. There is no <memory> implementation at present, so that cannot be made to work.
I've been puzzled by this for a while. To test this out, I made a simple program that just creates a std::string variable and prints it out to the screen. However, it doesn't include <string.h>.
#include <iostream>
using namespace std;
int main()
{
string name = "Test";
cout << name << endl;
return 0;
}
What confuses me is that this program compiles and runs perfectly. Right now I'm using the clang compiler that came with the XCode Developer Tools. Is this intended behavior? I hope this question isn't too ridiculous since I just started learning C++.
The reason you do not need to include the #include <string.h> header file is because when you include the #include <iostream> header file it includes std::string.
However, do not rely on it. What may work on your compiler may not work on another. Always include the proper header files.
To edit your example this is how you should use it:
#include <iostream>
#include <string>
int main()
{
std::string name = "Test";
std::cout << name << std::endl;
return 0;
}
Also note: why you should not use using namespace std;.
Why does my program compile successfully if I don't include <string.h>?
Because you don't use any definition / declaration from <string.h>.
program compiles and runs perfectly ... Is this intended behavior?
It is incidental behaviour.
There are no guarantees that one standard header wouldn't include other standard headers. It just so happens that <iostream> included <string> in this particular version of the standard library. Since there is no guarantee for this, it would be a mistake to rely on such transitive inclusion.
I would not expect the following code that prints the value of sin(pi/2) to work, without the inclusion of an additional header:
#include <iostream>
int main()
{
std::cout << sin(0.5*M_PI) << std::endl;
return 0;
}
and, as expected, upon compilation I get an error reading ‘sin’ was not declared in this scope and a similar error for the use of M_PI.
However, I am confused by the fact that if I include seemingly any boost library header, take just for example the lexical_cast.hpp, and instead run
#include <iostream>
#include <boost/lexical_cast.hpp>
int main()
{
std::cout << sin(0.5*M_PI) << std::endl;
return 0;
}
then the code works and it prints 1.
Why should including this boost header, which contains no definition of M_PI or sin(), allow this constant and function to be defined? Shouldn't I need to include a header, like math.h that includes these things for this to work?
Yes, it should work that way.
The boost headers you tried all have implicit dependencies (pow(), modf(), fmod(), log() etc).
This is a common thing in the C++ compilation model. Nothing to be alarmed by.
Guideline: always explicitly include the headers you directly depend on. And only those.
This prevents portability issues on platforms where the library header dependency tree differs e.g. <algorithms> and <numeric> aren't implicitly included with some other standard library headers (e.g. MSVC)
So, I have the following code, and it builds and runs perfectly, tried various values and all is well. You'll notice I use log10 function and I do not include cmath or math.h. Why does it still build and run fine? Are those libraries really needed? Why/Why not? Does it have anything to do with me using visual studio? Like, would it not compile if say I was using a different IDE or command prompt to compile it?
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << "Classify solutions as acidic or nonacidic" << endl<< endl;
//declaring double molar concentration
double mc = 1;
//using while and if statements to calculate pH in fixed notaion and acidic or nonacidic
while (mc != 0)
{
cout << "Please enter a molar concentration (or enter 0 to exit): ";
cin >> mc;
if (mc != 0)
{
cout << "Molar Conentration = " << scientific << mc << endl; //scientific notation
double pH = -log10(mc);
cout << "pH = " << fixed << setprecision(6) << pH << endl; //6 deciumals
if (pH > 7)
{
cout << "Nonacidic" << endl << endl;
}
else if (pH < 7)
{
cout << "Acidic" << endl << endl;
}
else
cout << "Neutral" << endl << endl;
}
}
//end program when inputing 0
cout << "End of Program" << endl;
return 0;
}
The code:
i = i++ + ++i;
may also compile okay, but that doesn't make it a good idea :-)
It would be wise to include headers for library functions that you use. You don't lose any functionality by doing so but you do guarantee the functionality will work (misuse notwithstanding).
Detailed analysis follows.
Even if an implementation is relaxed about this, the standard mandates it. C++11 17.6.2.2 Headers /3 states:
A translation unit shall include a header only outside of any external declaration or definition, and shall include the header lexically before the first reference in that translation unit to any of the entities declared in that header.
The gcc compiler, for example, will grumble bitterly about your code:
xyzzy.cpp: In function 'int main()':
xyzzy.cpp:22:34: error: 'log10' was not declared in this scope
double pH = -log10(mc);
^
As to why VC++ seemingly violates this rule, it has to do with the fact that header files are allowed to include other header files.
If you compile your code to produce pre-processor output (with /P), you'll find a line buried deep within it thus (at least in VS2013):
#line 1 "c:\\blah\\blah\\vc\\include\\cmath"
And a bit of analysis turns up the following hierarchy of includes:
iostream
istream
ostream
ios
xlocnum
cmath
(<xlocnum>, one of the internal headers used by <locale>, appears to need ldexp() from the <cmath> library, though there may be others as well).
That's further evidenced by the fact that VC++ does complain about the following code:
//#include <iostream>
using namespace std;
int main() {
double oneHundred = 100;
int two = log10 (oneHundred);
return two;
}
with:
error C3861: 'log10': identifier not found
but that error disappears the instant you uncomment the iostream inclusion line.
However, as previously stated, that is not behaviour you should rely on. If you are going to use a library function (or macro/template/whatever), it's up to you to include the correct header.
Otherwise your program compiling correctly is simply an accident.
As you've noticed, the code snippet you provided works in Visual Studio but not with other compilers. This is because of how the standard library is implemented for each compiler.
It turns out that when you include Visual Studio's implementation of <iostream>, you end up including a bunch of other headers indirectly, and one of these headers is <cmath>.
To see the exact chain, navigate to the standard library include directory. For me (I use Visual Studio 2013 Community Edition) this is located at
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include
Open iostream. Note the line #include <istream>
Open istream. Note the line #include <ostream>
Open ostream. Note the line #include <ios>
Open ios. Note the line #include <xlocnum>
Open xlocnum. Note the line #include <cmath>
Guess what? You included cmath when you included iostream... so your code is good to go, on Visual Studio at least. But, don't rely on implementation details or your code will break if you try to migrate it to another platform/toolchain.
For example, trying to compile the provided snippet using g++ on Cygwin results in the following error:
temp.cpp: In function ‘int main()’:
temp.cpp:22:34: error: ‘log10’ was not declared in this scope
double pH = -log10(mc);
This must mean g++'s implementation of <iostream> doesn't depend on <cmath>
I am very curious why I can use the math functions in C++ without including the "math.h". I can't find an answer with google search.
Here is the simple code I am executing. Everything is compiling and running.
#include <iostream>
using namespace std;
int main()
{
const float PI = acosf(-1);
cout << PI << endl;
return 0;
}
Any standard header is allowed to include any other standard header.
if you would compile the same with gcc-4.8 it would complain.
Keep in mind that this is not something to rely on if you want your code to be portable and compilable on different versions of the same or different compilers.