简体   繁体   English

C ++:模板化代码可使用clang ++编译并正常运行,但对于g ++则失败

[英]C++: Templated code compiles and runs fine with clang++, but fails with g++

Take a look at this implementation of a linked list: 看一下链表的此实现:

#include <memory>
#include <type_traits>
#include <iostream>

using namespace std;

template<typename D>
class List {
    struct Node {
        shared_ptr<D> data;
        Node* next;
        Node(shared_ptr<D> d, Node* p, Node* n) : data(d), next(n) {}
        ~Node() {
            data.reset();
            delete next;
        }
    };
    template <bool isconst = false> 
    struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
        typedef std::forward_iterator_tag iterator_category;
        typedef shared_ptr<D> value_type;
        typedef std::ptrdiff_t Distance;
        typedef typename conditional<isconst, const value_type&, value_type&>::type
                Reference;
        typedef typename conditional<isconst, const value_type*, value_type*>::type
                Pointer;
        typedef typename conditional<isconst, const Node*, Node*>::type
                nodeptr;
        iterator(nodeptr x = nullptr) : curr_node(x) {}
        iterator(const iterator<false>& i) : curr_node(i.curr_node) {}
        Reference operator*() const { return curr_node->data; }
        Pointer operator->() const { return &(curr_node->data); }
        template<bool A>
        friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
            return a.curr_node == b.curr_node;
        }
        template<bool A>
        friend bool operator!=(const iterator<A>& a, const iterator<A>& b) {
            return !(a.curr_node == b.curr_node);
        }
        friend class List<D>;
        iterator& operator++() { 
            curr_node = curr_node->next; 
            return *this; 
        }
        private:
            nodeptr curr_node;
    };
    public:
        List() {
            head = nullptr;
        }
        int len() const {
            int ret = 0;
            for (const auto& n : *this) {
                ret++;
            }
            return ret;
        }
        ~List() {
            delete head;
        }
        std::ostream& dump(std::ostream &strm) const {
            for (const auto s : *this) {
                strm << *s << std::endl;
            }
            return strm;
        }
        iterator<false> begin() {
            return iterator<false>(head);
        }
        iterator<false> end() {
            return iterator<false>(nullptr);
        }
        iterator<true> begin() const {
            return iterator<true>(head);
        }
        iterator<true> end() const {
            return iterator<true>(nullptr);
        }
    private:
        Node* head;
};

The part giving me problems is the iterator implementation for this list. 给我带来问题的部分是该列表的iterator实现。 The iterator template is supposed to provide both mutable and const iterators. 迭代器模板应该提供可变和const迭代器。

This is a program which uses this implementation: 这是一个使用此实现的程序:

#include "List.h"
#include <iostream>

int main( int argc, const char *argv[] ) {
    List<int> l;

    std::cout << l.len() << std::endl;
    return 0;
}

The program compiles and runs fine if I use clang++ , but the compilation fails for g++ with the following error: 如果我使用clang++ ,则程序可以编译并运行良好,但是对于g++ ,编译失败,并出现以下错误:

In file included from t.cpp:1:
List.h: In instantiation of ‘struct List<int>::iterator<false>’:
List.h:136:5:   required from ‘int List<D>::len() const [with D = int]’
t.cpp:7:24:   required from here
List.h:64:21: error: redefinition of ‘template<bool A> bool operator==(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’                                                
         friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
                     ^~~~~~~~
List.h:64:21: note: ‘template<bool A> bool operator==(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’ previously declared here                                        
List.h:69:21: error: redefinition of ‘template<bool A> bool operator!=(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’                                                
         friend bool operator!=(const iterator<A>& a, const iterator<A>& b) {
                     ^~~~~~~~
List.h:69:21: note: ‘template<bool A> bool operator!=(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’ previously declared here      

What's the cause of this error? 此错误的原因是什么? How can I fix this? 我怎样才能解决这个问题?

The problem seems to be here: 问题似乎在这里:

template <bool isconst = false> 
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
    template<bool A>
    friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
        return a.curr_node == b.curr_node;
    }

This is saying: For all values of isconst (the outer template parameter), define a template function template<bool A> bool operator== . 这就是说:对于isconst所有值(外部模板参数),请定义模板函数template<bool A> bool operator==

So instantiating iterator<true> will define template<bool A> bool operator== , and then instantiating iterator<false> will define template<bool A> bool operator== again, causing a redefinition error. 因此,实例化iterator<true>将定义template<bool A> bool operator== ,然后实例化iterator<false>将再次定义template<bool A> bool operator== ,从而导致重新定义错误。

Solution: Remove the inner template. 解决方案:卸下内部模板。 Have each instantiation of iterator only define its own operator== : iterator每个实例仅定义其自己的operator==

template <bool isconst = false> 
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {

    friend bool operator==(const iterator& a, const iterator& b) {
        return a.curr_node == b.curr_node;
    }

(Here iterator automatically refers to iterator<isconst> , ie the current instantiation.) (这里的iterator自动引用iterator<isconst> ,即当前实例。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果在模板化的 function 中使用了不完整的类型,则代码使用 g++ 但不是 clang++ 编译 - Code compiles with g++ but not clang++ if incomplete type is used in templated function g ++中的奇怪编译错误(clang ++可以正常编译) - Strange Compile Errors in g++ (clang++ compiles fine) 程序使用clang ++进行编译,但是g ++耗尽了RAM并失败 - Program compiles using clang++, but g++ exhausts the RAM and fails 使用clang ++和g ++,双嵌套模板类中的c ++ static int def失败 - c++ static int def in doubly nested template class fails with clang++ and g++ 将g ++代码移植到Clang ++问题 - porting g++ code to Clang++ issue `apply`模板在g ++中编译,但不在clang ++和vc ++中编译 - `apply` template compiles in g++ but not in clang++ and vc++ 基于范围的实现以g ++编译,但不是在clang ++中编译 - Range-based-for implementation compiles in g++ but not in clang++ 继承模板化的operator = in C ++ 14:与g ++和clang ++的不同行为 - Inheriting templated operator= in C++14: different behaviour with g++ and clang++ 自定义操纵器使用Visual C ++编译,但不使用g ++ / clang编译 - Custom manipulator compiles with Visual C++ but not g++/clang 此c ++模板代码有效吗? g ++编译它,但是clang不会 - Is this c++ template code valid? g++ compiles it but clang won't
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM