【问题标题】:A piece of code cannot be compiled by intel compiler but clang will compile it一段代码不能被intel编译器编译,但是clang会编译
【发布时间】:2015-10-25 00:35:40
【问题描述】:

以下代码是一个最低限度的工作(或可能不工作)示例。

它所做的基本上是将一堆 std::map 结构封装为基类中的私有成员。为了避免编写大量的 setter 和 getter,它们被实现为模板函数。

//  test.cpp

#include <map>
#include <iostream>    

enum class E0
{
    F0, F1, F2,
};       

基类的声明。

using std::map; 
class P_base
{
private:
    map<E0, int> m_imap;
    //  ...
    //  ... Other std::map members with different key types and value types.
public:
    map<E0, int> & imap;    
    //  ...
    //  ... Other std::map references.

    P_base() : imap(m_imap) {}    

    template<typename map_type, typename key_type, typename val_type>
    void set(map_type & m, const key_type & k, const val_type & v)
    {
        m[k] = v;
    }    

    template<typename map_type, typename key_type>
    auto access_to_map(const map_type & m, const key_type & k) -> decltype(m.at(k))
    {
        return m.at(k);
    }
};    

class P : private P_base
{
public:
    decltype(P_base::imap) & imap;    

    P() : P_base(), imap(P_base::imap) {}    

    template<typename map_type, typename key_type, typename val_type>
    void set(map_type & m, const key_type & k, const val_type & v)
    {
        P_base::set(m, k, v);
    }    

    template<typename map_type, typename key_type>
    auto access_to_map(const map_type & m, const key_type & k) -> decltype(P_base::access_to_map(m, k))
    {
        return P_base::access_to_map(m, k);
    }
};    

主要

int main(int argc, const char * argv[])
{
    using std::cout;
    using std::endl;    

    P op;    

    op.set(op.imap, E0::F0, 100);
    op.set(op.imap, E0::F1, 101);
    op.set(op.imap, E0::F2, 102);    

    cout << op.access_to_map(op.imap, E0::F1) << endl;

}


$ clang++ -std=c++11 test.cpp && ./a.out
101

但是如果我用 intel 编译器编译它(icpc 版本 15.0.3(gcc 版本 5.1.0 兼容)),编译器会给我这个错误消息(我根本不理解,尤其是当 clang 将编译代码):

$ icpc -std=c++ test.cpp && ./a.out
test.cpp(67): error: no instance of function template "P::access_to_map" matches the argument list
        argument types are: (std::__1::map<E0, int, std::__1::less<E0>, std::__1::allocator<std::__1::pair<const E0, int>>>, E0)
        object type is: P
  cout << op.access_to_map(op.imap, E0::F1) << endl;

而且不抱怨 set 功能也让我感到困惑。

有人知道这里发生了什么吗?

【问题讨论】:

  • g++在同一个地方拒绝代码,所以我猜icc的g++兼容模式是有效的!

标签: c++ templates c++11 clang icc


【解决方案1】:

注意:我的回答适用于 g++ - 希望它与 icc 相同。

这是一个较小的测试用例:

struct Base
{
    int func(int t) { return t; }
};

struct Der : Base
{
    template<typename T>
    auto f(T t) -> decltype(Base::func(t))
    {
        return t;
    }
};

int main(){ Der d; d.f(5); }

错误是:

mcv.cc: In function 'int main()':
mcv.cc:16:25: error: no matching function for call to 'Der::f(int)'
 int main(){ Der d; d.f(5); }
                     ^
mcv.cc:16:25: note: candidate is:
mcv.cc:9:7: note: template<class T> decltype (t->Base::func()) Der::f(T)
  auto f(T t) -> decltype(Base::func(t))
   ^
mcv.cc:9:7: note:   template argument deduction/substitution failed:
mcv.cc: In substitution of 'template<class T> decltype (t->Base::func())     Der::f(T) [with T = int]':
mcv.cc:16:25:   required from here
mcv.cc:9:38: error: cannot call member function 'int Base::func(int)' without object
  auto f(T t) -> decltype(Base::func(t))

这可以通过将decltype(Base::func(t)) 更改为decltype(this-&gt;Base::func(t)) 来解决。对我来说,相应的修复会修复您的代码示例。

显然,编译器不认为Base::func(t) 应该使用*this 作为隐藏参数来调用。我不知道这是 g++ 的 bug,还是 clang 超出了职责范围。

请注意,在 C++14 中,由于函数只有一个 return 语句,因此可以完全省略尾随返回类型:

template<typename T>
auto f(T t)
{
    return t;
}

【讨论】:

  • 谢谢。这修复了它,我完全同意这是一个 g++ 错误。我在自己的笔记本电脑上使用 gcc 5.1.0 对其进行了测试。它通过了。安装了icpc的服务器运行的是OSX,其gcc是xcode版本,不是单独安装的。
猜你喜欢
  • 1970-01-01
  • 2020-06-03
  • 1970-01-01
  • 2012-12-22
  • 2017-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多