// Bug 724496 - Unscoped call to visit_each may resolve to non-libsigc++ impl
// See https://bugzilla.gnome.org/show_bug.cgi?id=724496#11

#include <iostream>

namespace sigc
{

template <class T_functor>
struct visitor
{
  template <class T_action>
  static void do_visit_each(const T_action& _A_action, const T_functor& _A_functor)
  {
    std::cout << "do_visit_each(), primary visitor\n";
    _A_action(_A_functor);
  }
};

template <class T_action, class T_functor>
void visit_each(const T_action& _A_action, const T_functor& _A_functor)
{
  std::cout << "visit_each()\n";
  sigc::visitor<T_functor>::do_visit_each(_A_action, _A_functor);
}

template <class T_functor>
struct simple_sigc_struct
{
  explicit simple_sigc_struct(const T_functor& _A_functor)
    : functor_(_A_functor) {}

  T_functor functor_;
};

template <>
template <class T_type>
struct visitor<simple_sigc_struct<T_type> >
{
  template <class T_action>
  static void do_visit_each(const T_action& _A_action,
                            const simple_sigc_struct<T_type>& _A_argument)
  {
    std::cout << "do_visit_each(), visitor<simple_sigc_struct>\n";
    sigc::visit_each(_A_action, _A_argument.functor_);
  }
};

} // namespace sigc

namespace another_ns
{

template <class T_functor>
struct simple_ns_struct
{
  explicit simple_ns_struct(const T_functor& _A_functor)
    : functor_(_A_functor) {}

  T_functor functor_;
};

} // namespace another_ns

namespace sigc
{

template <>
template <class T_type>
struct visitor<another_ns::simple_ns_struct<T_type> >
{
  template <class T_action>
  static void do_visit_each(const T_action& _A_action,
                            const another_ns::simple_ns_struct<T_type>& _A_argument)
  {
    std::cout << "do_visit_each(), visitor<another_ns::simple_ns_struct>\n";
    sigc::visit_each(_A_action, _A_argument.functor_);
  }
};

} // namespace sigc

template <class T_functor>
struct simple_struct
{
  explicit simple_struct(const T_functor& _A_functor)
    : functor_(_A_functor) {}

  T_functor functor_;
};

namespace sigc
{

template <>
template <class T_type>
struct visitor< ::simple_struct<T_type> >
{
  template <class T_action>
  static void do_visit_each(const T_action& _A_action,
                            const ::simple_struct<T_type>& _A_argument)
  {
    std::cout << "do_visit_each(), visitor<::simple_struct>\n";
    sigc::visit_each(_A_action, _A_argument.functor_);
  }
};

} // namespace sigc

struct Functor1
{
  explicit Functor1(int i) : i_(i) {}
  void operator()() const { std::cout << "Functor1()(), " << i_ << "\n"; }
  int i_;
};

template <typename T_functor>
struct Action1
{
  void operator()(const T_functor& _A_functor) const
  {
    std::cout << "Action1()()\n";
   _A_functor();
  }
};

int main()
{
  std::cout << "   sigc::simple_sigc_struct\n";
  sigc::visit_each(Action1<Functor1>(),
                   sigc::simple_sigc_struct<Functor1>(Functor1(1)));

  std::cout << "\n   another_ns::simple_ns_struct\n";
  sigc::visit_each(Action1<Functor1>(),
                   another_ns::simple_ns_struct<Functor1>(Functor1(2)));

  std::cout << "\n   ::simple_struct\n";
  sigc::visit_each(Action1<Functor1>(),
                   ::simple_struct<Functor1>(Functor1(3)));
  return 0;
}

