Функция-член шаблона в классе шаблона не найдена при вызове экземпляра - PullRequest
1 голос
/ 25 марта 2020
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 вызов не компилируется с ошибкой

.../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);
                                      ~~~^

Удаление template не помогает:

.../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

Я использую Clang 9 с C Стандарт ++ 14.

alloc2 работает в качестве обходного пути, поэтому я просто хочу знать, почему alloc1 нет или как правильно объявить / вызвать его.

РЕДАКТИРОВАТЬ: оказывается, что предоставление специализации Allocator<API::CPU>::malloc / free вместо специализации Allocator<API::CPU> дает поведение, которое я ожидал, но, вероятно, наследование будет более подходящим в моей исходной ситуации.

Ответы [ 2 ]

3 голосов
/ 25 марта 2020

class Allocator<API::CPU> специализация просто не определяет функцию-член; Он определяется только в шаблоне generi c. Если вы хотите избежать повторения одного и того же определения для нескольких спецификаций, вы можете использовать наследование. Вот, например, такой:

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

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

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

PS Ваш alloc1 является личным, поэтому у вас все равно не будет доступа к нему вне класса.

2 голосов
/ 25 марта 2020

В этой специализации класса

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

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

нет функции-члена alloc1.

И в этих операторах

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

используется эта специализация шаблон класса.

...