-
January 26th, 2013, 09:41 AM
#1
namespace problems
Hi, The simplified code compiles correctly under GCC but not MSVC. why ? If I put Option struct in its own named namespace or remove the namespace Util, it compiles correclty. How can I make it work for both compilers ?
Code:
#include <vector>
#include <iostream>
/*default vector IO*/
template <class T>
std::ostream& operator << (std::ostream& os, const std::vector<T>& p) {
return os;
}
template <class T>
std::istream& operator >> (std::istream& is, std::vector<T>& p) {
return is;
}
/*Utililty functions*/
namespace Util {
/*options*/
struct Option {
friend std::istream& operator >> (std::istream& is, Option& p) {
return is;
}
friend std::ostream& operator << (std::ostream& os, const Option& p) {
return os;
}
};
/*parameters*/
struct Parameters{
std::vector<int>* test;
bool read(std::string str,std::istream& is) {
is >> *test;
return false;
}
};
/*end*/
}
void main() {
Util::Parameters params_vec_int;
params_vec_int.read("test",std::cin);
}
Last edited by dshawul; January 26th, 2013 at 12:18 PM.
-
January 26th, 2013, 10:49 AM
#2
Re: template instantiation
as far as I can tell VC is right at rejecting that code, because name lookup should ignore the globally defined vector<T> stream operators once those pulled in the Util namespace are found. I'm quite surprised gcc accepts it though ...
anyway, the solution is to either put the vector<T> stream operators in namespace std ( as it should be ) :
Code:
Code:
#include <vector>
#include <iostream>
namespace std {
/*default vector IO*/
template <class T>
std::ostream& operator << (std::ostream& os, const std::vector<T>& p) { return os; }
template <class T>
std::istream& operator >> (std::istream& is, std::vector<T>& p) { return is; }
}
...
or to pull the Option class in the unnamed namespace
Code:
namespace {
namespace details {
struct Option {
double x;
friend std::istream& operator >> (std::istream& is, Option& p) {
return is;
}
friend std::ostream& operator << (std::ostream& os, const Option& p) {
return os;
}
};
}
using details::Option;
}
or ... well, it depends on what you're trying to achieve with that anonymous namespace.
-
January 26th, 2013, 11:14 AM
#3
Re: template instantiation
Hi, thanks very much. Both methods work. What I don't understand is that the overloaded IO operators of Option class have different types than the default ones,so why should there be a conflict ?
I edited my previous post and it works if I had a specialized IO operators for Int types even if it is placed in the same namespace.
-
January 26th, 2013, 12:00 PM
#4
Re: template instantiation
Originally Posted by dshawul
I edited my previous post
not a good idea, now nobody will understand my answer above ...
Originally Posted by dshawul
What I don't understand is that the overloaded IO operators of Option class have different types than the default ones,so why should there be a conflict ?
you should not confuse overload resolution and name lookup. When the compiler finds an unqualified function name ( as in "f(x)" or in "x >> y" ) it first collects all name declarations filling a list of possible candidates and then and only then it applies the overloading resolution rules to find the best matching one ( provided some exists and is unique ).
Now, unqualified name lookup is performed by either traversing the declarative regions tree or via ADL ( = argument dependent lookup ). In the former case, the traversal stops when at least a name is found. In your original example that name was the operator>> in the Util namespace ( that borrows the names from the unnamed namespace where the Option struct injects its friend operators ). Hence, the compiler ignores the globally defined operator>>, giving you an error during overload resolution.
If you put those vector<T> operators in Util the compiler will consider them as candidates along with the Option operators, selecting the right one during overload.
If you put those vector<T> operators in the std namespace as I did above then ADL will include them in the candidate list ( this means that, among other things, the compiler will search also the namespace in which the types of the operator>> arguments reside, that for std::vector is exactly std ).
If you put Option ( and its operators ) in its own namespace as I did above then the name search will stop at global scope hence including your vector<T> operators.
-
January 26th, 2013, 12:20 PM
#5
Re: template instantiation
Thanks a lot for the thorough explanation. Now I understand perfectly.
I have edited my original post with the source code that produces the error so that others understand
your explanation.
Thanks again.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|