【问题标题】:Template Specialization of Member Method成员方法的模板特化
【发布时间】:2021-05-07 14:25:13
【问题描述】:

我在获取成员方法的模板特化以正确编译时遇到问题。我已经阅读了所有建议的文章,并且在每一篇文章中,课程本身都是模板化的。就我而言,我没有模板类,只是一个简单的模板方法。

这是一个例子:

//In Test.h
class Test {
public:
    template <typename T>
    void foo(const T& v) {
        //Do something generic with T
    }
};

//In Test.cpp
template <>
void Test::foo<unsigned int>(const unsigned int& v) {
    //Do something specific with unsigned int
}

根据这篇文章multiple definition of template specialization when using different objects,我已将专业化放在我的 CPP 文件中。但是,这会导致当我执行以下操作时不会调用专用函数:

#include "Test.h"

int main() {
    Test t;
    unsigned int a;
    
    t.foo(a);
}

但是,如果我将专业化放在 .h 文件中,则会收到大量“重复定义”错误。

解决这个问题的正确方法是什么?

谢谢!

编辑

这是我的实际代码的 sn-p

#ifndef BYTEARRAY_H_
#define BYTEARRAY_H_

#include <memory>
#include <limits.h>
#include <string.h>
#include <iterator>

namespace tw {

class ByteArray {
public:
    //...

    size_t append(const void* source, size_t sourceSize);

    template <typename T>
    inline size_t append(const T& v) {
        static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable (i.e. via memcpy) to use ByteArray::append<T>");

        return append(reinterpret_cast<const void*>(&v), sizeof(T));
    }

private:
    void _deepCopy();

    //-- Member Data --
    /**
     * @brief Total number of bytes allocated and pointed to by _memory
     */
    size_t _capacity;

    /**
     * @brief Current "virtual" size of the array
     */
    struct {
        size_t _length : (CHAR_BIT * sizeof(size_t)) - 1;
        bool _isStatic : 1;
    };

    /**
     * @brief Shared/smart pointer to the underlying, allocated array of bytes
     */
    std::shared_ptr<uint8_t[]> _memory;

    /**
     * @brief A small amount of memory for use when capacity() < sizeof(size_t)
     *        rather than allocated memory on the heap for _memory
     */
    uint8_t _memoryDirect[sizeof(size_t)];
};

template <>
size_t ByteArray::append<ByteArray>(const ByteArray& v) {
    return append(v.data().get(), v.length());
}

template <>
size_t ByteArray::append<uint8_t>(const uint8_t& v) {
    ASSERT(!isFull());

    dataMutable().get()[_length++] = v;

    return 1;
}

} /* namespace tw */

#endif /* BYTEARRAY_H_ */

【问题讨论】:

  • 你必须在标题中声明特化。
  • 错字? “我已将专业化放在我的 CPP 中......发生了一些事情......” vs “但是,如果我将专业化放在 CPP 文件中,......还有别的......”
  • @largest_prime_is_463035818 是的,这是一个错字。对于那个很抱歉。当我将我的特化移动到头文件时,我编译得很好,但是链接器会抛出“多重定义”错误。
  • 你需要标题保护,但如果你只包含一次,就像这里的例子一样,这实际上不应该发生
  • 完全专业化不再是模板,因此不再隐含inline。您必须将它们标记为inline

标签: c++ templates template-specialization


【解决方案1】:

感谢@Jarod42 的评论。我的问题是我的原始模板被指定为内联,但是,当我添加我的专业化时,它们不再被隐式内联。

作为参考,这就是我要更改的全部内容:

template <>
inline size_t ByteArray::append<ByteArray>(const ByteArray& v) {
    return append(v.data().get(), v.length());
}

【讨论】:

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