Template member function in a template class not found when called on an instance

此生再无相见时 提交于 2021-01-28 19:01:55

问题


namespace {
enum class API { CPU, CUDA };

template <API Api>
class Allocator {
    void* malloc(int size) const;
    void free(void* ptr) const;

    template <typename T>
    T* alloc1(int num) const {
        return static_cast<T*>(malloc(num * static_cast<int>(sizeof(T))));
    }
};

template <typename T, API Api>
T* alloc2(const Allocator<Api> allocator, int num) {
    return static_cast<T*>(allocator.malloc(num * static_cast<int>(sizeof(T))));
}

template <>
class Allocator<API::CPU> {
public:
    void* malloc(int size) const { return nullptr; }

    void free(void* ptr) const {}
};

Allocator<API::CPU> allocator;
int* ptr1 = allocator.template alloc1<int>(1);

int* ptr2 = alloc2<int>(allocator, 1);

}

alloc1 call doesn't compile with error

.../src/test.cc:29:32: error: no member named 'alloc1' in '(anonymous namespace)::Allocator<API::CPU>'
int* ptr1 = allocator.template alloc1<int>(1);
                               ^
.../src/test.cc:29:38: error: expected unqualified-id
int* ptr1 = allocator.template alloc1<int>(1);
                                     ^
.../src/test.cc:29:42: error: expected '(' for function-style cast or type construction
int* ptr1 = allocator.template alloc1<int>(1);
                                      ~~~^

Removing template doesn't help:

.../src/test.cc:29:33: error: expected '(' for function-style cast or type construction
int* ptr1 = allocator.alloc1<int>(1);
                             ~~~^
.../src/test.cc:29:23: error: no member named 'alloc1' in '(anonymous namespace)::Allocator<API::CPU>'; did you mean 'malloc'?
int* ptr1 = allocator.alloc1<int>(1);
                      ^~~~~~
                      malloc

I am using Clang 9 with C++14 standard.

alloc2 works as a workaround, so I just want to know why alloc1 doesn't or what is the proper way to declare/call it.

EDIT: it turns out that providing specializations of Allocator<API::CPU>::malloc/free instead of a specialization of Allocator<API::CPU> gives the behavior I expected, but probably inheritance will be more appropriate in my original situation.


回答1:


class Allocator<API::CPU> specialisation simply does not define the member function; It is only defined in the generic template. If you want to avoid repeating same definition for multiple specilisations, you can use inheritance. Like this for example:

struct BaseAllocator {
    template <typename T>
    T* alloc1(int num) const {
        ...
    }
};

template <API Api>
class Allocator : public BaseAllocator {
    ...
};

template <>
class Allocator<API::CPU> : public BaseAllocator {
    ...
};

P.S. Your alloc1 is private, so you wouldn't have access to it from outside the class anyway.




回答2:


In this specialization of the class

template <>
class Allocator<API::CPU> {
public:
    void* malloc(int size) const { return nullptr; }

    void free(void* ptr) const {}
};

there is no member function alloc1.

And in these statements

Allocator<API::CPU> allocator;
int* ptr1 = allocator.template alloc1<int>(1);

there is used this specialization of the class template.



来源:https://stackoverflow.com/questions/60847063/template-member-function-in-a-template-class-not-found-when-called-on-an-instanc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!