【问题标题】:friend function in CUDA C++CUDA C++ 中的友元函数
【发布时间】:2018-11-06 02:41:20
【问题描述】:

我正在解决一个问题,即 A 类和 B 类在命名空间 test0 中声明,而 A 类的友元函数 f 在命名空间 test1 中声明。函数 f 接收 B 类对象的引用作为参数。这是一个简化的例子。

namespace test0 {
    class B;
}

namespace test1 {
    void f(test0::B& b);
}

namespace test0 {
    class A {
        friend void test1::f(test0::B& b);
    };
}

该代码适用于 g++。但是nvcc给出如下编译错误。

a.cu:11:22: error: ‘B’ has not been declared
        friend void test1::f(test0::B& b);
                    ^
a.cu:11:27: error: ‘void test1::f(int&)’ should have been declared inside ‘test1’
        friend void test1::f(test0::B& b);
                        ^

你能帮我找出问题所在吗?提前谢谢你。

【问题讨论】:

  • 不应该是friend void test1::f(B& b);吗?您位于 test0 命名空间中,因此编译器可能会感到困惑。或friend void test1::f(::test0::B& b); 以确保解析来自全局命名空间。第二个错误很可能是第一个错误的结果。
  • @Yksisarvinen 第二个错误是第一个错误的结果。 friend void test1::f(::test0::B& b); 引发与原始错误相同的错误。 friend void test1::f(B& b); 即使使用 g++ 也不起作用。

标签: c++ compiler-errors cuda nvcc friend-function


【解决方案1】:

重要的是要了解 nvcc 不是编译器,它是编译器驱动程序,在这两种情况下,代码都是用 gcc 编译的,错误是 gcc 生成的错误。如果你把这段代码放在一个.cc扩展文件中,通过nvcc编译,就不会出错了。

但是在编译 CUDA 代码时(在本例中为 .cu 文件),在您的代码和编译它的最终 g++ 传递之间有一些中间处理阶段。在幕后,正在发生的事情是您的代码正在被 CUDA C++ 前端解析器转换为:

# 1
# 2
namespace test0 { 
# 3
    class B; 
# 4
}
# 6
namespace test1 { 
# 7
    void f(test0::B & b); 
# 8
}
# 10
namespace test0 { 
# 11
    class A { 
# 12
        friend void test1::f(B & b); 
# 13
    }; 
# 14
}

将其与原始的 friend void test1::f(test0::B& b); 进行比较,您可以看到命名空间已被 cudafe++ 传递删除。我不知道为什么它已被删除,但这是错误的根源。

如果这是您的应用程序中的真正问题,我建议将此作为错误报告给 NVIDIA。

【讨论】:

    【解决方案2】:

    经过 NVIDIA 开发团队的审查,这似乎暴露了 gnu 编译器中的一个错误。确实,nvcc 工具链的前端处理创建了一个主机代码(传递给主机编译器),它删除了b 类型的命名空间限定,但这应该是可以接受的,因为B 已经已在 test0 命名空间中声明。

    gnu 社区似乎有already been reported

    作为支持数据点,Fedora 25 上的 clang++ 3.9.1 编译了@talonmies 给出的answer 中报告的代码,没有错误也没有警告。在我在 Fedora25 上通过 gnu 6.4.1 进行测试时,gnu 工具链仍然抛出错误。我并没有声称这是一个证明点,只是建议 gnu 中的错误声明 可能 可能是正确的。我不是语言专家。此外,我不想在这里开始争论。这不是这个问题或答案的目的。

    NVIDIA 开发团队已对该问题进行审查,并希望在未来的 CUDA 版本中提供修复或解决方法。

    同时,建议的源代码级解决方法是在类A 中为B 使用虚拟类型定义。即:

    class A {
        typedef B dummy_t;
        friend void test1::f(dummy_t & b);
    };
    

    更新:

    该问题应在 CUDA 10.1.105 (CUDA 10.1) 中解决

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多