“没有可行的转换”用柠檬作为clang但对g ++有效

时间:2015-11-10 14:41:05

标签: c++11 g++ clang++ lemon-graph-library

目前,我尝试在我们的项目中加入柠檬库。 大多数开发人员都使用Windows,他们使用MSVC进行编译,但我负责(使用此部分)使用gcc和clang进行编译。

我遇到了一个错误,因为gcc没有重现,我设法减少了代码:

#include <lemon/dfs.h>

int main() {
    lemon::ListDigraph g{};
    lemon::ListDigraph::Node node = g.nodeFromId(42);
    lemon::Dfs<lemon::ListDigraph> dfs{g};
    lemon::SimplePath<lemon::ListDigraph> path = dfs.path(node);
    return 0;
}  

使用gcc,没有错误。

/usr/bin/g++-5 -std=c++11 -Wall -O3  -I${SRC_ROOT}/external/lemon/latest -I${BIN_ROOT}/lemon -o ${TMP_ROOT}/core/src/core.cpp.o -c ${SRC_ROOT}/core/src/core.cpp

但是对于clang:

/usr/bin/clang++-3.7 -std=c++11 -Wall -stdlib=libc++ -O3 -I${SRC_ROOT}/external/lemon/latest -I${BIN_ROOT}/lemon -o ${TMP_ROOT}/core/src/core.cpp.o -c ${SRC_ROOT}/core/src/core.cpp

In file included from ${SRC_ROOT}/core/src/core.cpp:1:
In file included from ${SRC_ROOT}/external/lemon/latest/lemon/dfs.h:31:
${SRC_ROOT}/external/lemon/latest/lemon/path.h:408:23: error: no viable
      conversion from 'typename PredMapPath<ListDigraph, NodeMap<Arc> >::RevArcIt' to
      'lemon::ListDigraphBase::Arc'
        data[index] = it;;
                      ^~

备注

  • SRC_ROOTBIN_ROOTTMP_ROOT因可读性而被替换
  • 片段源代码不起作用,但应该编译(我将更正真正的大代码)
  • 我真的需要真正源代码的c ++ 11功能。
  • gcc 5
  • clang 3.7
  • lemon 1.3.1

问题

  • 我忘了扯旗了吗?
  • 柠檬与clang完全兼容吗?
  • 如何解决此错误?

1 个答案:

答案 0 :(得分:2)

这是double dispatch相关问题

中的代码 http://lemon.cs.elte.hu/hg/lemon/file/9fd86ec2cb81/lemon/path.h#l443

template <typename CPath>
void buildRev(const CPath& path) {
    int len = path.length();
    data.resize(len);
    int index = len;
    for (typename CPath::RevArcIt it(path); it != INVALID; ++it) {
        --index;
        data[index] = it;; // sic!
    }
}

依赖于用户定义的右侧迭代器cast-operator

http://lemon.cs.elte.hu/hg/lemon/file/9fd86ec2cb81/lemon/bits/path_dump.h#l139

operator const typename Digraph::Arc() const {
    return path->predMatrixMap(path->source, current);
}

但是分配表达式的左手类型

http://lemon.cs.elte.hu/hg/lemon/file/9fd86ec2cb81/lemon/list_graph.h#l89

class Arc {
    friend class ListDigraphBase;
    friend class ListDigraph;
protected:
    int id;
    explicit Arc(int pid) { id = pid;}
public:
    Arc() {}
    Arc (Invalid) { id = -1; }
    bool operator==(const Arc& arc) const {return id == arc.id;}
    bool operator!=(const Arc& arc) const {return id != arc.id;}
    bool operator<(const Arc& arc) const {return id < arc.id;}
};

没有自定义赋值运算符,但是clang尝试匹配右侧转换的单参数自定义ctor。然后失败了。

修补上面显示的右侧lemon/path.h, line #443 使用简单的显式转换运算符调用

   data[index] =  it.operator const typename Digraph::Arc();; 

使代码至少使用clang(3.5)进行编译。

柠檬开发商必须决定这是否是理想的行为;应该为此提交错误报告。