Compiling the following code:

#include <iostream>
#include <sstream>
#include <tuple>
#include <type_traits>

namespace NS
{
    struct Point
    {
        int x;
        int y;
    };

    template <typename StreamType>
    inline StreamType& operator<<(StreamType& stream, const Point& obj)
    {
        return stream << std::make_tuple(
                                         obj.x,
                                         obj.y);
    }

    struct Serialize
    {
        template <typename ...T>
        struct for_each
        {
            for_each(const std::tuple<T...>& t) : t_(t) { }
            const std::tuple<T...>& t_;

            template <std::size_t pos = 0, typename StreamType>
            StreamType& operator()(StreamType& stream, typename
std::enable_if<(pos >= sizeof...(T))>::type* = nullptr)
            {
                return stream;
            }

            template <std::size_t pos = 0, typename StreamType>
            StreamType& operator()(StreamType& stream, typename
std::enable_if <(pos < sizeof...(T))>::type* = nullptr)
            {
                if (pos) { stream << stream.sep_; }
                stream << std::get<pos>(t_);
                return this->operator()<pos + 1>(stream);
            }
        };

        template <typename ...T>
        Serialize(const std::tuple<T...>& t) :
            sep_(","), quoted_(true) { (*this) << t; }

        template <typename T>
        Serialize(const T& obj, bool autoProviders = true) :
            sep_(autoProviders ? "_" : ", "), quoted_(false) {
NS::operator<<(*this, obj); }

        std::string str() const { return stream_.str(); }

        template <typename ...T>
        Serialize& operator<<(const std::tuple<T...>& t)
        {
            for_each<T...> functor(t);
            return functor(*this);
        }

        template <typename T>
        Serialize& operator<<(const T& t)
        {
            stream_ << t;
            return (*this);
        }

        Serialize& operator<<(const std::string& s)
        {
            if (!quoted_) { stream_ << s; }
            else { stream_ << '\'' << s << '\''; }
            return (*this);
        }

        std::ostringstream stream_;
        const char* sep_;
        bool quoted_;
    };

    template <typename ...T>
    inline std::ostream& operator<<(std::ostream& stream, const
std::tuple<T...>& t)
    {
        return stream << Serialize(t).str();
    }
}

int main()
{
    std::ostringstream os;
    NS::Point p = {1, 2};
    os << p;
    return 0;
}

produces the error:

clang++ --std=c++11 test_operator_adl.cpp
test_operator_adl.cpp:17:17: error: call to function 'operator<<' that is
      neither visible in the template definition nor found by
argument-dependent
      lookup
                return stream << std::make_tuple(
                              ^
test_operator_adl.cpp:92:5: note: in instantiation of function template
      specialization 'NS::operator<<<std::basic_ostringstream<char> >'
requested
      here
        os << p;
           ^
test_operator_adl.cpp:82:23: note: 'operator<<' should be declared prior
to the
      call site
        inline std::ostream& operator<<(std::ostream& stream, const std:...
                             ^
1 error generated.

I would have thought that since all the necessary definitions have been
seen before the spot where the templates are instantiated and operator<<
is used that we have satisfied the requirement that "operator<< should
be declared prior to the call site". Is this a bug or I just don't
understand things correctly?

--
Jens Jorgensen
jorgen...@lowtechsolutions.net

This e-mail and its attachments are intended only for the individual or entity 
to whom it is addressed and may contain information that is confidential, 
privileged, inside information, or subject to other restrictions on use or 
disclosure. Any unauthorized use, dissemination or copying of this transmission 
or the information in it is prohibited and may be unlawful. If you have 
received this transmission in error, please notify the sender immediately by 
return e-mail, and permanently delete or destroy this e-mail, any attachments, 
and all copies (digital or paper). Unless expressly stated in this e-mail, 
nothing in this message should be construed as a digital or electronic 
signature. For additional important disclaimers and disclosures regarding KCG’s 
products and services, please click on the following link:

http://www.kcg.com/legal/global-disclosures

_______________________________________________
cfe-users mailing list
cfe-users@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-users

Reply via email to