带有T = char *的`const T`不是`const char *`?

时间:2018-06-02 17:53:56

标签: c++ templates pointers const typedef

我有一个通用链表:

template <class E>
class linked_element {
    linked_element<E> *last = nullptr, *next = nullptr;
    const E elem;
public:
    explicit linked_element(const E elem) : elem(elem) { }
    linked_element(const linked_element& cpy) : next(cpy.next), last(cpy.last), elem(cpy.elem) { }
    ~linked_element() {
        if(next != nullptr) next->last = last;
        if(last != nullptr) last->next = next;
    }
    linked_element& operator =(linked_element& other) {
        if(this != &other) {
            last = other.last;
            next = other.next;
            elem = other.elem;
        }
        return *this;
    }

    void add(linked_element<E> *next) {
        next->last = this;
        this->next = next;
    }

    const E& get() {
        return elem;
    }

    linked_element<E> *getLast() {
        return last;
    }

private:
    linked_element() = default;
};

template <class T>
class linked_list {
    linked_element<T*> *end = nullptr;
    std::size_t size = 0;
public:
    linked_list() = default;

    void push(const T& elem) {
        auto e = new linked_element<T*>(&elem);
        if(end != nullptr) end->add(e);
        end = e;
        size++;
    }

    T& peek() {
        checkAndCrash();
        return *(end->get());
    }

    void pop() {
        checkAndCrash();
        auto tmp = end->getLast();
        delete end;
        end = tmp;
        size--;
    }

    bool empty() {
        return size == 0;
    }

    void checkAndCrash() {
        //...
    }
};

但是当我尝试将它与char一起使用时:

int main() {
    using std::string;

    string a("a"), b("b"), c("c");

    linked_list<char> list;

    list.push('a');
    list.push('b');
    list.push('c');

    while (!list.empty()) {
        std::cout << list.peek() << std::endl;
        list.pop();
    }
    return 0;
}

我明白了:

In file included from .../linked_list/main.cpp:3:0:
.../linked_list/linked_list.hpp: In instantiation of ‘void linked_list<T>::push(const T&) [with T = char]’:
.../linked_list/main.cpp:12:15:   required from here
.../linked_list/linked_list.hpp:53:40: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
   auto e = new linked_element<T*>(&elem);
                                        ^
[...]

对我来说没有意义,如果elem属于const T& &elem类型应该是const T*类型(我使用debbuger并且它是)然后构造函数是new linked_element<char*>(const char*),因此任何地方都不应转换为char*。我错过了什么?我尝试在谷歌搜索,但我似乎无法得到任何答案(也许我在寻找错误的东西?)。

感谢您的时间。

1 个答案:

答案 0 :(得分:3)

我有T = int。现在我想要一个const T。因此,常量Tconst int

我有T = char*。现在我想要一个const T。所以一个常数T,所以一个常数char*所以char *const。这是一个重要的区别。指针本身是const,而不是它指向的值。

如果您将T中的const T替换为其值char*,则表示您获得const char*,但这不是类型系统的工作方式: )

类似地,对于T = char&const T将是char&而不是const char&,因为不存在常量引用这样的情况,因此会被忽略。