Portál AbcLinuxu, 1. června 2025 12:21


Dotaz: c++ templates and overloading

25.2.2010 16:46 ::: | skóre: 14 | blog: e_lama
c++ templates and overloading
Přečteno: 437×
Odpovědět | Admin
Zdavim, mam nasledujici 2 soubory (a.cpp a b.cpp). Jediny rozdil je ze v b.cpp jsem presunul string_t a string_traits do vlastniho jmenneho prostoru. Pritom a.cpp jde zkompilovat (gcc) bez problemu, ale b.cpp skonci s chybou:
/usr/lib/gcc/3.4.4/include/c++/bits/stl_function.h: In member function `bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = xxx::string_t]':
b.cpp:54:   instantiated from here
/usr/lib/gcc/3.4.4/include/c++/bits/stl_function.h:227: error: no match for 'operator<' in '__x < __y'
Zajimavy je ze yyy::less funguje ale std::less ne. Pritom jsem yyy::less vytvoril jako kopii std::less...

a.cpp:
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <functional>

namespace yyy
{
  template<typename _Tp>
    struct less : public std::binary_function<_Tp, _Tp, bool>
    {
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x < __y; }
    };
}

struct string_t { };

template <typename string_type_>
struct string_traits;

template <>
struct string_traits<string_t>
{
        typedef string_t string_type;
};

template <typename A, typename B>
struct both_exist: public boost::mpl::true_ {};

template <typename T, typename U>
inline
typename boost::enable_if
<
        both_exist
        <
                typename string_traits<T>::string_type,
                typename string_traits<U>::string_type
        >,
        bool
>::type operator < (const T &str1, const U &str2)
{ }

int main()
{
        yyy::less<string_t> cmp;
        std::less<string_t> cmp1;
        string_t a;
        string_t b;
        cmp(a, b);
        cmp1(a, b);
}

b.cpp:
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <functional>

namespace yyy
{
  template<typename _Tp>
    struct less : public std::binary_function<_Tp, _Tp, bool>
    {
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x < __y; }
    };
}

namespace xxx {

        struct string_t { };

        template <typename string_type_>
        struct string_traits;

        template <>
        struct string_traits<string_t>
        {
                typedef string_t string_type;
        };

}

template <typename A, typename B>
struct both_exist: public boost::mpl::true_ {};

template <typename T, typename U>
inline
typename boost::enable_if
<
        both_exist
        <
                typename xxx::string_traits<T>::string_type,
                typename xxx::string_traits<U>::string_type
        >,
        bool
>::type operator < (const T &str1, const U &str2)
{ }

int main()
{
        yyy::less<xxx::string_t> cmp;
        std::less<xxx::string_t> cmp1;
        xxx::string_t a;
        xxx::string_t b;
        cmp(a, b);
        cmp1(a, b);
}


Řešení dotazu:


Nástroje: Začni sledovat (1) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

25.2.2010 17:39 Sinuhet | skóre: 31
Rozbalit Rozbalit vše Re: c++ templates and overloading
Odpovědět | | Sbalit | Link | Blokovat | Admin
Mrvi vam to boost. Kdyz ho vyhodite (ve vasem priklade je stejnak zbytecny), tak se to zkompiluje.
25.2.2010 18:11 ::: | skóre: 14 | blog: e_lama
Rozbalit Rozbalit vše Re: c++ templates and overloading
Diky za tip. Zjistil jsem ze boost includuje <utility> a to vytvari v std "operator <" pro porovnani std::pair. Tak jsem vyzkousel pridat "operator <" i do yyy:
namespace yyy {
        class x;
        inline bool operator < (x const &a, x const &b) { }
}
a dela me to stejnou chybu i s yyy::less. Takze zrejme ten muj "operator <" neni pristupny v zadnym namespace kde uz existuje jiny "operator <".

Nejak to nechapu... chapal bych kdyby to muj operator prekrylo vzdycky, ale proc to dela jenom kdyz je string_t a string_traits v xxx ??
25.2.2010 18:44 Sinuhet | skóre: 31
Rozbalit Rozbalit vše Re: c++ templates and overloading
25.2.2010 18:53 ::: | skóre: 14 | blog: e_lama
Rozbalit Rozbalit vše Re: c++ templates and overloading
diky, uz jsem to taky dohledal. Takze je to vlastnost a ten "univerzalni operator <" (prispevek dole) asi nijak neudelam?
25.2.2010 18:48 ::: | skóre: 14 | blog: e_lama
Rozbalit Rozbalit vše Re: c++ templates and overloading
tak jsem zjistil ze kdyz ten template operator < presunu do xxx tak to funguje.

Problem je (see http://en.wikipedia.org/wiki/Argument_dependent_name_lookup), ze napr pri pouziti yyy::less, gcc nejdriv najde yyy::operator<, potom prohleda namespacy asociovany s argumentama a najde xxx::operator<, a root namespace uz neprohledava...

Tak nevim. Je tohle vlastnost nebo chyba ? A je teda mozny udelat operator <, ktery by fungoval na vsechny string tridy co maji string_traits, at uz jsou v jakymkoli jmennym prostoru ?
25.2.2010 18:59 Sinuhet | skóre: 31
Rozbalit Rozbalit vše Re: c++ templates and overloading

Co by "univerzalni" operator< mel delat? To je problem kazde implementace stringu, aby mela i svoji definici porovnani, ktera bude ve stejnem namespacu, takze vsechno bude fungovat, jak ma.

25.2.2010 19:20 ::: | skóre: 14 | blog: e_lama
Rozbalit Rozbalit vše Re: c++ templates and overloading
moje predstava byla ze bych mel nekolik typu stringu, napr std::string alokovany na halde, potom nejaka vlastni trida pro retezce jen na zasobniku, a mozna i dalsi kombinace...

Ke kazdymu bych udelal string_traits, kde by byly funkce begin() a end() ktery vrati ukazatele na zacatek/konec retezce a "operator <" bych potom mohl pouzit na porovnavani ruznych trid stringu...

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.