问题
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