【问题标题】:How to specialise template class constructor in C++ [duplicate]如何在 C++ 中专门化模板类构造函数 [重复]
【发布时间】:2022-12-13 01:35:29
【问题描述】:

我正在练习 C++,我想使用模板实现一些数据结构。

我想为 List<char> 创建一个接受 C++ string 作为参数的构造函数,但我不想为其余类型创建这样的构造函数(因为创建一个List<double> 来自 string,例如)。

有没有办法在 C++ 中实现这一点?

这是我的代码:

#include <iostream>
#include <string>
#include <cstring>

using namespace std;

template <typename T> class CollectionInterface {
public:
    virtual T get();
    virtual void set(int index, T value);
    virtual void add(T value);
    virtual int length();
};

template <typename T> class ListItem {
public:
    T value;
    ListItem* next;
    ListItem* prev;
};

template <typename T> class List: public CollectionInterface<T> {
public:
    List(){}
    List(T* arr, int length){
        init(arr,length);
    }
    ~List(){

    }

protected:
    void init(T* arr, int length){

    }
    ListItem<T>* first;
    ListItem<T>* last;
};

template<char> class List<char> {
public:
    List<char>(string s){
        char char_array[s.length() + 1];
        strcpy(char_array, s.c_str());
        this->init(char_array,s.length());
    }
};

int main()
{
    List<char> list("Hello World!");

    //cout << "Hello World!" << endl;
    return 0;
}

它显示以下错误:

第 40 行:“List”的部分特化不使用其任何模板参数

第 45 行:“List<char>”中没有名为“init”的成员

【问题讨论】:

  • 完全专门化模板类是template&lt;&gt; class List&lt;char&gt; { ... };
  • 此外,VLA 不是标准的一部分,因此不应使用。无论如何都不需要这样做:this-&gt;init(s.data(), s.length()); 应该可以解决问题,您可能还是想在这里创建一个副本,所以如果您将 init 的签名更改为 void init(T const* arr, int length)this-&gt;init(s.c_str(), s.length()); 可能就足够了
  • 有没有办法从 List<char> 中调用非专用函数?我收到错误消息:“List<char>”中没有名为“init”的成员
  • 不幸的是,当我正在寻找答案时这个问题已经结束,但基本上我会在类之外实现转换并引入一个通过概念(或 SFINAE pre C++20)限制的构造函数模板。这是我用简化类创建的示例:godbolt.org/z/Yn7GYMTsc

标签: c++ c++-templates


【解决方案1】:

做你想做的事,你不需要特化整个List类。只需为 List&lt;T&gt; 类提供一个用于 string 输入的重载构造函数,然后使用 SFINAE 为非 char 列表禁用该构造函数,例如:

template <typename T> class List: public CollectionInterface<T> {
public:
    ...

    template <typename U = T>
    List (typename enable_if<is_same<U, char>::value, string>::type const &s)
    {
        init(const_cast<char*>(s.c_str()), s.length());
    }

    ...
};

Online Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-02
    • 2015-03-12
    • 1970-01-01
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    相关资源
    最近更新 更多