[cfe-users] is this an ADL bug or not?

Jens Jorgensen jorgensen at lowtechsolutions.net
Mon Mar 17 18:26:16 PDT 2014


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
jorgensen at 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




More information about the cfe-users mailing list