部分模板专用化 c++ 未完全使用不完整类型无效

Invalid use of incomplete type for partial template specialization c++

本文关键字:用不完 无效 类型 专用 c++      更新时间:2023-10-16

我正在尝试专门化一个类方法foo()。这适用于完整的模板专用化。但是,这不适用于部分模板专用化。

这里是在GCC和Clang上编译良好的示例代码:

#include <iostream>
#include <string>
template <typename Key, typename Value>
struct SimpleKey {
    Key   key;
    Value value;
    void foo() const { 
        std::cout << "base" << std::endl; 
    }
};
/*
// Uncomment this and it won't work !
template<typename Key>
void SimpleKey<Key, std::string>::foo() const {
    std::cout << "partial" << std::endl; 
}
*/
template<>
void SimpleKey<int, std::string>::foo() const {
    std::cout << "full" << std::endl; 
}

int main() {
    SimpleKey<double, std::string> key1{1.0,"key1"};
    key1.foo();
    SimpleKey<int, std::string> key2{1,"key2"};
    key2.foo();
}

取消注释相关代码时,我收到的 Clang 和 GCC 错误是:

错误:无效使用不完整的类型"struct SimpleKey>" void SimpleKey::foo() const {

我应该怎么做才能让部分模板专业化以"最少"的努力正常工作?

可以显式专用化类模板的特定隐式实例化的成员函数。但这是部分专业化所不允许的。如果您不想编写完整的部分专用化,则可以考虑使用标记调度:

private:
void foo(std::true_type /*value_is_string*/) const { /* "partial" */ }
void foo(std::false_type /*value_is_string*/) const { /* "base" */ }
public:
void foo() const { return foo(std::is_same<Value, std::string>()); }

或将foo()重构为您部分专用的基类模板。

这不可能直接。(可惜了,这个语法很好)但是你可以做这样的事情:

namespace detail {
    inline void f_(int i) { /* spé for int */}
    inline void f_(long i) { /* spé for long*/}
    /* other spe... */
}
template<class T>
struct Foo{
    void f(T arg) { detail::f_(arg);}
};

它没有那么直接,但仍然易于阅读。