I have seen that even if you don't add std:: before stoi(s.substr(3,4)) (where s="123456789") it works fine, and also if you write std::stoi(s.substr(3,4)) the result is the same. So, is writing it like std::stoi(s.substr(3,4)) mandatory, or is it just good practice?
std::string s = "123456789";
int ans = stoi(s.substr(3,4));
std::cout<<ans;
std::string s = "123456789";
int ans = std::stoi(s.substr(3,4));
std::cout<<ans;
Both gives the same answer. And also sometimes writing std::stoi(s.substr(3,4)); gives an error.
It compiles without std:: because of the argument-dependent lookup.
I say it's a good practice to use std::stoi because:
It's more obvious that a standard function is being called.
It will not break if someone defines a variable named stoi prior to your code. This can be fixed by adding using std::stoi;, but since you call it once, it's more verbose than calling std::stoi directly.
It is considered good practice to add std:: namespace, so you can avoid conflicts if you use different libraries etc.
The probable reason it gives you an error sometimes is because you probably don't include the string header of the standard library:
#include <string>
but it is difficult without seeing the error, so please provide the details
Likely, if you can use stoi and get the same result as std::stoi, you might be using namespace std already.
This is not always desirable, depending on the project philosophy and the rest of your code suggests that you shouldn't depend on it.
edit: in this case, OP does not use using namespace std and something more subtle is going on (thanks #HolyBlackCat).
stoi() exists in the std namespace, so using stoi() without std:: works if there is a preceding using namespace std; or using std::stoi; statement, or when passing in a std::string object as an argument value due to Argument-Dependent Lookup (since string and stoi() are in the same namespace).
Related
I want to write log2() function for a new datatype that I defined myself Array. So it will look like this
#include <iostream>
#include <cmath>
Array log2(Array& A)
{
Array C=A;
for (int i=0; i<A.size(); i++)
C[i]=log2(A[i]);
return C;
}
despite other functions like sin, cos, etc, this one (log2) is not declared under std namespace. so even using the following
std::log2(A[i])
the compiler does not resolve that inside log2 is suppoed to be the built-in c function. I persist to use the same name (log2) for simplicity of the code.
This is the error message
error: invalid initialization of reference of type 'Array&' from expression of type 'double'
SOLVED: It worked when I switched to -std::C++ 11.
std::log2 was introduced in C++11. Make sure you have a C++11 compliant compiler (e.g. gcc4.8 or later, compile with -std=c++11), and use std::log2 inside your function.
If you don't use std::log2, then the compiler cannot find the standard function (as you are not using namespace std;) and tries to use yours, which of course is not defined for doubles, and you get an error.
My personal opinion is that you should try to avoid naming your function the same as a standard one, due to headaches that can later appear.
As far as I know, the built-in function log2 is not declared in namespace std.
You should use the following code to call the standard log2 function:
log2(A[i]);
I hope my answer helped.
As we already know :: is global namespace. And we have already know that using namespace has some downsides.
So we decide to type less and type in the beggining of our file using ::std::cout;, but we can also type using std::cout;. So is there any difference?
Some people write ::std::cout in order to be absolutely sure that they're getting the cout from the standard library, since the leading :: roots the type at the global namespace.
Otherwise it's conceivable that lookup could find some ::haha::trolling::std::cout name. However, I'd say that this is unlikely.
I do sometimes write ::std in short function templates that are designed to be highly reusable, just for maximum portability, but it's fairly uncommon. I've seen one SO contributor who stuck to it religiously, but that's about it.
I am trying to migrate some code from boost::tuple to std::tuple but I'm getting some weird errors: after I invoke using namespace std (and never boost), I expect an unqualified tie to resolve to std::tie. However, this seems to fail when the tuple contains a boost container pointer, for example.
#include <tuple>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#ifdef USE_STD
#define TIE std::tie
#else
#define TIE tie
#endif
typedef boost::multi_index_container<
int,
boost::multi_index::indexed_by<
boost::multi_index::ordered_non_unique<
boost::multi_index::identity<int>
>
>
> Set;
std::tuple< int, int* > make_i_ptr();
std::tuple< int, Set* > make_set();
int main()
{
using namespace std;
int i;
int* i_ptr;
Set* set_ptr;
tie(i, i_ptr) = make_i_ptr();
TIE(i, set_ptr) = make_set();
return 0;
}
If I compile with g++ -std=c++0x -c test.cpp -DUSE_STD, all is well. However, without -D USE_STD, I get compile errors suggesting g++ tries to use boost::tuples::tie. I'm using g++ 4.8.1 and boost 1.55.0. Do you think this is a bug with boost? Or is there some spec I'm missing?
Lookup is complicated. The problem as others have mentioned is Argument Dependent Lookup or ADL. The rules for ADL were added to allow the definition of operators in the same namespace as the types they refer to, and enabling lookup to find those operators when present. This was later extended to all other functions in the process of standarization.
The issue here is that tie(...) is a function call. The compiler will attempt regular lookup from the point of use (inside main) it will move out to the enclosing namespace. The using directive will add ::std into the lookup search when it hits the root namespace (common ancestor of ::std and ::main). At that point, since the identifier resolves to a function, ADL will kick in.
ADL adds the namespaces associated to the arguments of the function call, which in this case is boost:: (fundamental types like int have no associated namespaces). At this point the compiler sees two declarations of tie: std::tie and boost::tie, causing ambiguity.
As you already know the solution is to qualify the call to std::tie (which I would advice that you use even without this issue). Regarding the comment:
If ADL makes it resolve to boost::tie for... "my convenience" and then the compilation fails, shouldn't that be a clue to the compiler that it picked the wrong function?!
I don't know what the exact error you are getting is (I don't use boost, and I don't know what possible overloads of std::tie it contains). If the problem is indeed one of ambiguity, the problem is that the compiler cannot resolve the identifier, and cannot continue the process. At that point it stops and asks for the programmer to resolve it. If the error is that it uniquely picked boost::tie and it later failed in the assignment, it means that theres is an overload of boost::tie that is a better match than std::tie and that was selected. At a later time the assignment from std::tuple may have failed, but the compiler cannot know whether the problem was during lookup, or whether it is the assignment itself (did you intend on assigning that variable? maybe a different one?) so again it fails and tells you what the problem is.
Note that in general the process of compilation is always moving forward, the compiler does not backtrack to double guess its own decisions*. There is a set of rules, and those rules are applied at each step. If there is ambiguity, compilation stops, if not, then there is a single best candidate and this point is resolved, moving to the next. Attempting to go back to undo decisions would turn the compilation process into something painfully slow (the number of paths that could be taken would be exponential).
* As always there are some exceptions but those are just exceptions, notably during overload resolution if a template is picked as the best candidate but substitution of type arguments fail, it is discarded and the next best candidate is chosen.
I'm working on a very large project and in one file we all of the sudden got a compile-time error where the compiler seems to think that our call to winsock.h bind() is actually a call to std::bind(). It seems that somewhere in a include file there is using namespace std code snippet. We could try and find where these using namespace std are in use and remove them, but perhaps there is a better way to do this?
You can change your calls to use ::bind() to specify the global namespace.
Yes, this is unfortunate. As I described at http://gcc.gnu.org/ml/libstdc++/2011-03/msg00143.html the std::bind template is a better match unless you use exactly the right argument types:
The problem is that the socket bind() function has this signature:
int bind(int, const sockaddr*, socklen_t);
so the call in the example using a non-const pointer finds that the
variadic template std::bind is a better match. The same would happen
if the third argument was any integral type except socklen_t.
Your code would work with GCC because I added a conforming extension to GCC's std::bind to prevent this ambiguity, by removing std::bind from the overload set if the first argument is "socket-like", which I defined using is_integral and is_enum. That doesn't help with other implementations though.
Removing the using namespace std; is a good idea anyway, but may not be entirely sufficient, because an unqualified call to bind() that happens to use a type defined in namespace std (such as std::size_t) could still find std::bind by argument dependent lookup. Jonathan Potter's answer is the best way to ensure you get the right function: qualify it as ::bind.
Why does the following code compile in C++11 and does not in C++03? (both gcc and cl)
#include <string>
#include <iostream>
#include <fstream>
int main(int argc, char* argv[]) {
const std::string t("Hello");
std::ofstream out(t);
}
Why don't the C++03 streams accept std::string as the constructor parameter? Was this decision based on something or did it happen accidentally?
The code fails when compiled with a strictly conforming C++03 compiler because the constructor that takes a std::string was only added in C++11.
As to the question, "was it based on something smart", as the interface was added, it can be inferred that there was no technical reason for it to be omitted.
It's an addition of convenience as, if you have a std::string, you can always call .c_str() to get a C string suitable for use with the old interface. (As the documentation in C++11 says , the constructors that take std::string have exactly the same effect as calling the corresponding constructor which takes a const char* with the result of calling .c_str() on the string.)
As I recall, this was discussed on c.l.c++.m some years ago, and Andrew Koenig (I think it was Andrew, anyway) said it was actually brought up during some meetings, but the idea of accepting a string was quickly conflated with the idea of accepting a wstring as well, and from there turned into a discussion about support for internationalized character sets in file names, and ... shortly after that the whole idea was dropped because it had opened a big can of worms nobody was prepared to deal with right then.
They had simply forgotten about adding the string constructor in C++03. Now that's fixed. This time round other things were forgotten, like make_unique. There's always something more that one could have done. C++03 also forgot to specify default arguments for function templates, which are now included.
Edit: As #Charles says, it may not be a literal "forgetting", but rather, it's something that clearly should be there, but just hadn't been specified for some reason or another. Further examples are given by std::next/std::prev, which are a great relief, and std::to_string and std::stoi/d/ul/ull, which again make perfect sense, but nobody had gotten around to specifying them until this time round. There isn't necessarily a deep reason for their previous absence.