【问题标题】:Template member function in a template class not found when called on an instance在实例上调用时未找到模板类中的模板成员函数
【发布时间】:2020-03-25 10:36:54
【问题描述】:
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

我正在使用具有 C++14 标准的 Clang 9。

alloc2 是一种解决方法,所以我只想知道为什么 alloc1 不这样做,或者声明/调用它的正确方法是什么。

编辑:事实证明,提供 Allocator&lt;API::CPU&gt;::malloc/free 的特化而不是 Allocator&lt;API::CPU&gt; 的特化会产生我预期的行为,但在我原来的情况下,继承可能更合适。

【问题讨论】:

  • 您的专业没有定义alloc1(),仅此而已。你不清楚这部分的哪一部分?你看到alloc1() 在你的专业化Allocator&lt;API::CPU&gt; 中定义了吗?我没看到。你看不到它。你的编译器也没有。
  • 专业化和继承是两个非常不同的东西。如果您想从一个共同的基础继承不同的专业化,那么您需要这样做
  • 我怀疑您希望将基本模板中的实现用作默认实现,类似于 Haskell 的类型类,但这不是模板的工作方式。
  • 是的,这正是我所期望的。

标签: c++ templates c++14


【解决方案1】:

class Allocator&lt;API::CPU&gt; 特化根本不定义成员函数;它仅在通用模板中定义。如果您想避免对多个规范重复相同的定义,您可以使用继承。比如这样:

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

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

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

附:您的alloc1 是私有的,因此无论如何您都无法从课堂外访问它。

【讨论】:

  • 我设法失去了public,同时以某种方式减少了问题,哦,好吧。
  • @AlexeyRomanov 是的,当问题根本无法调用该函数时很容易错过 :) 我更喜欢使用 struct 作为最小示例,除非问题与访问说明符直接相关。
【解决方案2】:

在这个类的特化中

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);

使用了这个类模板的特化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多