LINUX.ORG.RU

дурацкий (просто чтобы понять) вопрос про c++ locales

 ,


0

1
There's even a little convenience feature: if L is a locale 
object, you can compare two strings by writing L(x, y) instead
of going through the nuisance of calling use_facet and then
invoking a collate member function

(c) http://lafstern.org/matt/col2_new.pdf

Круто! Но:

#include <locale>
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    locale L = locale::classic();
    cout << L("kekeke", "kekeke") << endl;
}

Приводит к:

g++ locale_kekeke.cpp 
locale_kekeke.cpp: In function ‘int main(int, char**)’:
locale_kekeke.cpp:8:33: error: no match for call to ‘(std::locale) (const char [7], const char [7])’
    8 |     cout << L("kekeke", "kekeke") << endl;
      |                                 ^

Что он мог иметь ввиду говоря you can compare two strings by writing L(x, y)?

Ответ на: комментарий от dissident

Не так подсказываешь

template<class CharT, class Traits, class Alloc>
bool operator()( const basic_string<CharT,Traits,Alloc>& s1,
                 const basic_string<CharT,Traits,Alloc>& s2) const;

DllMain ()
Ответ на: комментарий от dissident

Неправильный синтаксис и не те аргументы для шаблона как DllMain говорит. Надо:

cout << L.operator()<char, char_traits<char>, allocator<char>>("kekeke", "kekeke") << endl;
xaizek ★★★★★ ()
Ответ на: комментарий от xaizek

OMG. А разве locale не могло сделать как-то так:

template<typename CharT>
<
   template <class> class Traits,
   template <class> class Alloc
>
bool operator()( const basic_string<CharT,Traits<CharT>,Alloc<CharT>>& s1,
                 const basic_string<CharT,Traits<CharT>,Alloc<CharT>>& s2) const;

Сорри если это неверно синтактически, но что-то такое я видел в Alexandrescu «Modern….длинное название» ? Зачем повторять тоже самое?

dissident ★★ ()
Ответ на: комментарий от dissident

В принципе могли (с правильным синтаксисом), но это бы немного ограничило реализацию трэйтов и аллокаторов. Может поэтому и не стали. Ну и предполагали, что на вход будут подаваться уже готовые объекты строк, наверное.

xaizek ★★★★★ ()
Ответ на: комментарий от xaizek

В принципе могли (с правильным синтаксисом)

Как-то так?..

#include <iostream>
using namespace std;

template<typename T>
class my_basic_string
{
public:    
    my_basic_string(const char* c_str) { /* do nothing */ }
};

template<typename T>
class MyTraits
{
public:
    static void keke() { /* Do nothing */ }
};

template<typename T>
class MyAlloc
{
public:
    static void keke() { /* Do nothing */ }
};


template<typename CharT>
class MyLocale
{
public:
    template<
        class AMyTraits = MyTraits<CharT>,
        class AMyAlloc = MyAlloc<CharT>
    >
    bool operator()( const my_basic_string<CharT>& s1,
                     const my_basic_string<CharT>& s2) const
    {
        AMyTraits::keke();
        AMyAlloc::keke();
        return true;
    }
};

int main(int argc, char* argv[])
{
    cout << MyLocale<char>()("kekeke",  "kekeke") << endl;
}

Пошел утоться в унитазе и/или читать SICP.

dissident ★★ ()
Последнее исправление: dissident (всего исправлений: 3)
Ответ на: комментарий от dissident

Я думал в стиле:

#include <iostream>
using namespace std;

class MyLocale
{
public:
    template<
        typename CharT,
        template <class> class Traits = char_traits,
        template <class> class Alloc = allocator
    >
    bool operator()( const basic_string<CharT, Traits<CharT>, Alloc<CharT>>& s1,
                     const basic_string<CharT, Traits<CharT>, Alloc<CharT>>& s2) const
    {
        return true;
    }
};

int main(int argc, char* argv[])
{
    cout << MyLocale().operator()<char>("kekeke",  "kekeke") << endl;
}

Но оно так не компилируется.

xaizek ★★★★★ ()
Ответ на: комментарий от xaizek

И у меня брат от этого умер:

#include <iostream>
using namespace std;

template<
    class T1,
    template <typename> class T2,
    template <typename> class T3
>
class my_basic_string {
public:
        my_basic_string(const char*) { /* Do nothing */ }
};


template<typename T> class my_char_traits {};
template<typename T> class my_allocator {};


class MyLocale
{
public:
    template
    <
        typename CharT,
        class MyTraits = my_char_traits<CharT>,
        class MyAlloc = my_allocator<CharT>
    >
    bool operator()( const my_basic_string<CharT, MyTraits, MyAlloc>& s1,
                     const my_basic_string<CharT, MyTraits, MyAlloc>& s2) const
    {
        return true;
    }
};

int main(int argc, char* argv[])
{
    cout << MyLocale().operator()<char>("kekeke",  "kekeke") << endl;
}

Приводит к:

tmpl_wtf.cpp:29:68: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T1, template<class> class T2, template<class> class T3> class my_basic_string’
   29 |     bool operator()( const my_basic_string<CharT, MyTraits, MyAlloc>& s1,
      |            
dissident ★★ ()
Ответ на: комментарий от xaizek
Template argument deduction requires exact matches 

Т.е. вот так можно:

#include <iostream>
using namespace std;

template<typename CharT> class my_char_traits {};

template<typename CharT> class my_allocator {};

template
<
    typename CharT,
    class MyTraits = my_char_traits<CharT>,
    class MyAllocator = my_allocator<CharT>
>
class my_basic_string {
public:
    my_basic_string(const char*) { /* Do nothing */ }       
};


class MyLocale
{
public:
    template
    <
        typename CharT,
        template <typename> class MyTraits = my_char_traits,
        template <typename> class MyAllocator = my_allocator
    >
    bool operator()( const my_basic_string<CharT,MyTraits<CharT>,MyAllocator<CharT>>& s1,
                     const my_basic_string<CharT,MyTraits<CharT>,MyAllocator<CharT>>& s2) const
    {
        return true;
    }
};

int main(int argc, char* argv[])
{
    my_basic_string<char> a1("keke");
    my_basic_string<char> a2("keke");
    
    cout << MyLocale(a1,  a2) << endl;
//    cout << MyLocale().operator()<char>("kekeke",  "kekeke") << endl;
}

А вот то, что закоментировано внизу уже нельзя. :-|

dissident ★★ ()
Последнее исправление: dissident (всего исправлений: 2)
Ответ на: комментарий от dissident

Можно извратится с identity:

#include <iostream>
using namespace std;

template<typename CharT> class my_char_traits {};

template<typename CharT> class my_allocator {};

template
<
    typename CharT,
    class MyTraits = my_char_traits<CharT>,
    class MyAllocator = my_allocator<CharT>
>
class my_basic_string {
public:
    my_basic_string(const char*) { /* Do nothing */ }
};

template <typename T>
struct make
{
    typedef T type;
};

class MyLocale
{
public:
    template
    <
        typename CharT,
        template <typename> class MyTraits = my_char_traits,
        template <typename> class MyAllocator = my_allocator
    >
    bool operator()( typename make<const my_basic_string<CharT,MyTraits<CharT>,MyAllocator<CharT>> &>::type s1,
                     typename make<const my_basic_string<CharT,MyTraits<CharT>,MyAllocator<CharT>> &>::type s2) const
    {
        return true;
    }
};

int main(int argc, char* argv[])
{
    my_basic_string<char> a1("keke");
    my_basic_string<char> a2("keke");

    //cout << MyLocale()(a1,  a2) << endl;
    //cout << MyLocale()(a1,  "keke") << endl;
    //cout << MyLocale()("keke", a2) << endl;
    cout << MyLocale().operator()<char>("kekeke",  "kekeke") << endl;
}

Но так надо всегда явно указывать параметр.

xaizek ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.