CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Sep 2010
    Posts
    39

    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.

  2. #2
    Join Date
    Oct 2008
    Posts
    1,456

    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.

  3. #3
    Join Date
    Sep 2010
    Posts
    39

    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.

  4. #4
    Join Date
    Oct 2008
    Posts
    1,456

    Re: template instantiation

    Quote Originally Posted by dshawul View Post
    I edited my previous post
    not a good idea, now nobody will understand my answer above ...

    Quote Originally Posted by dshawul View Post
    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.

  5. #5
    Join Date
    Sep 2010
    Posts
    39

    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
  •  





Click Here to Expand Forum to Full Width

Featured