我可以使用 C++20 概念进行部分模板专业化吗?

Cel*_*ine 1 c++ templates c++-concepts c++20

我在计算机科学课上接到一个作业,要求String<T>用 C++ 实现一个类,该类的print方法将抛出异常,除非T = char. template<typename T> class String所以我为此定义了一个方法:

void print(std::basic_ostream<T> stream) {
    throw StringTypeError("Can't print with these types");
}
Run Code Online (Sandbox Code Playgroud)

并定义了这样的专业化:

template<>
void String<char>::print(std::basic_ostream<char> stream) {
    for(unsigned long i = 0; i < size; i++)
        stream << charAt(i);
}
Run Code Online (Sandbox Code Playgroud)

这完全有效,但是我最近发现了一些概念,并决定允许使用IO流中的print()任何类型。我创建了一个小概念:<<>>

template<typename T>
concept IO = requires(T a) {
    std::cout << a;
    std::cin  >> a;
};
Run Code Online (Sandbox Code Playgroud)

并试图以这种方式改变我的专业:

template<IO T>
void String<T>::print(std::basic_ostream<T> stream) {
    for(unsigned long i = 0; i < size; i++)
        stream << charAt(i);
}
Run Code Online (Sandbox Code Playgroud)

但编译器拒绝并显示“模板重新声明中的类型约束不同”错误。

我是否犯了一个可以纠正的错误,或者是否不可能以这种方式使用概念?(如果是这样,有没有类似概念的替代方案?

dfr*_*fri 8

有没有类似概念的替代方案?

有一个适合这项工作的工具,一个特别好的新功能,其中包含概念及其相关的要求子句,这是 C++20 之前的 SFINAE 不可能实现的,即可以声明类模板的非模板成员函数带有要求子句。这意味着您可以print在主模板中定义两个互斥的成员函数:

template<typename T> 
class String {
    void print(std::basic_ostream<T>&) requires (!IO<T>) {
        throw StringTypeError("Can't print with these types");
    }

    void print(std::basic_ostream<T>& stream) requires (IO<T>) {
        for(unsigned long i = 0; i < size; i++)
            stream << charAt(i);
    }
    // ...
};
Run Code Online (Sandbox Code Playgroud)