Własny operator new w namespace

0

Cześć!

Staram się poskładać do kupy moje poprzednie wypociny i zastanawiam się jak sensownie nazwać i jak trzymać dostęp do nowych alokatorów czy operatorów new/delete.
Postanowiłem zrobić przestrzeń dla przykładu mymem.
Chcę w tej przestrzeni trzymać np. mymem::allocator (podobnie jak w std), jakieś funkcje pomocnicze.
Problem pojawił się dla new/delete. Pomyślałem by zastosować przy pisaniu taką składnie:

/* ... */
int main(){
    //int * i = new int(2);
    int * i = mymem::_new<int>(2);

    std::cout << std::dec << *i << std::endl;

    /* ... */
    return 0;
}

Przykładowy _new alokujący pamięć w zmiennej statycznej (coś ala sbrk).

namespace mymem
{

    // example of memory
    static char   memory[1024*64];
    static char * memory_end = memory;
    
    template<typename _Tp>
    _Tp * alloc(size_t n){
        char * ptr = memory_end;
        memory_end += n;
        if( (memory_end - memory) > sizeof(memory))
            std::__throw_bad_alloc();
        return reinterpret_cast<_Tp*>(ptr);
    }
    
    template<typename _Tp, typename... _Args>
    _Tp * _new(_Args&&... __args){
        _Tp * p = alloc<_Tp>(sizeof(_Tp));
        ::new((void *)p) _Tp(std::forward<_Args>(__args)...);
        return p;
    }

};

Właśnie, jak zauważyliście, musiałem nazwać _new bo inaczej:

expected unqualified-id before 'new'
     _Tp * new(_Args&&... __args){
           ^~~

Żeby tak zrobić to new musi być zadeklarowane jako operator, niestety w namespace wywala błąd.

void* mymem::operator new(std::size_t)' may not be declared within a namespace
     void * operator new(std::size_t count){
                                          ^

Oczywiście w klasie nie ma problemu:

class Foo
{
    void * operator new(std::size_t count){

    }
};

Jak więc to jest że operator ::new nie jest w klasie a działa?

0

Znalazłem:

3.7.3.1 Allocation functions [basic.stc.dynamic.allocation]

[..] An allocation function shall be a class member function or a global function; a program is ill-formed if an allocation function is declared in a namespace scope other than global scope or declared static in global scope. [..]

Jak w takim razie zrobić globalnego new (void* operator new(std::size_t sz){ /*...*/ }) tylko dla typów/klas z mojego namespace'a?

2

3.7.4.1 An allocation function shall be a class member function or a global function; a program is ill-formed if an allocation function is declared in a namespace scope other than global scope or declared static in global scope.

0

Jeśli chce swoje operatory new/delete w swojej przestrzeni, to takie rozwiązanie będzie najlepsze?

namespace mymem{

    template <typename _Tp>
    using allocator = std::allocator<_Tp>;

#if 0
    using string = std::basic_string<char, std::char_traits<char>, allocator<char> >;
#else

    // jesli chce dodac swoje operatory new/delete, musze dziedziczyc...
    class string: public std::basic_string<char, std::char_traits<char>, allocator<char> >
    {
    public:
        void * operator new(size_t size){
            std::cout << __FUNCTION__ << " size: " << std::dec << size << std::endl;
            return std::malloc(size);
        }
        void operator delete(void *p){
            std::cout << __FUNCTION__ << std::endl;
            return std::free(p);
        }

        // a jak dziedzicze, to operatory trzeba przepisac, np. tak
        using std::string::operator=;
        using std::string::operator+=;
        using std::string::operator[];
        // ale trzeba przepisywac, da sie bardziej ulatwic sobie zycie?
    };
#endif
};

Mało uśmiecha mi się "przepisywanie" operatorów, nawet w postaci jak powyżej.

2

Możesz napisać sobie templatowy operator new z jakimś customowym alokatorem per typ/policy. Eewntualnie zdefiniuj sobie memory area z różnymi policy i wyspecjalizuj go per typy z tego namespace.

1 użytkowników online, w tym zalogowanych: 0, gości: 1