在 friend sub class 中使用 base 的私有方法——NVCC 中的编译器错误?
using private method from base in friend sub class -- compiler bug in NVCC?
在尝试使用英特尔线程构建模块编译一些 CUDA 代码时,我发现了我认为是 nvcc
中的错误。以下最小示例使用 g++
5.4:
编译良好
class Sub;
class Other;
namespace internal {
class Base
{
private:
friend class ::Sub;
static void foo(::Sub& b);
static void foo(::Other& c);
};
}
class Sub : private internal::Base
{
public:
using internal::Base::foo;
};
void internal::Base::foo(Sub& b)
{
}
int main(int argc, char *argv[])
{
Sub *b;
b->foo(*b);
// Sub::foo(*b);
return 0;
}
但是如果我用 nvcc
8.0 结合相同的主机编译器编译它,使用
nvcc -x cu -arch=sm_35 -c minimal.cc
我收到以下有趣的错误:
../minimal.cc: In function ‘int main(int, char**)’:
../minimal.cc:28:21: error: ‘internal::Base’ is an inaccessible base of ‘Sub’
如果将 Base
移出 internal
命名空间并移至全局命名空间,则会出现更具描述性的错误:
../minimal.cc: In function ‘int main(int, char**)’:
../minimal.cc:6:12: error: ‘class Base Base::Base’ is inaccessible
class Base
^
../minimal.cc:32:5: error: within this context
b->foo(*b);
^
../minimal.cc:32:11: error: ‘Base’ is an inaccessible base of ‘Sub’
b->foo(*b);
很明显,这似乎是由于使用指针调用静态方法的方式有点不标准,如果该行被注释掉的行替换,它编译得很好。
有人可以确认这是有效的 C++ 并因此是 nvcc
中的错误,还是 g++
不知何故仍然乐于接受的无效 C++?
我对此进行了更多研究,发现它确实是 nvcc
编译阶段之一的问题。使用 --save-temps
,并查看生成的 .cu.cpp.ii
文件,结果发现这一行
b->foo(*b);
被以下内容取代
(b->internal::Base::foo(*b));
这不会用 g++
编译,从那时起 foo
在 Sub
中导出为 public 的事实就丢失了。毕竟,这试图从 class 所在的 private
基址显式访问它。使用其他类型的调用 (Sub::foo
) 不会导致生成任何额外代码。
我断定这是 nvcc
中的错误。有趣的是,如果未在 Base
.
中声明第二个重载 void foo(::Other &c)
,则此替换 不会 发生
在尝试使用英特尔线程构建模块编译一些 CUDA 代码时,我发现了我认为是 nvcc
中的错误。以下最小示例使用 g++
5.4:
class Sub;
class Other;
namespace internal {
class Base
{
private:
friend class ::Sub;
static void foo(::Sub& b);
static void foo(::Other& c);
};
}
class Sub : private internal::Base
{
public:
using internal::Base::foo;
};
void internal::Base::foo(Sub& b)
{
}
int main(int argc, char *argv[])
{
Sub *b;
b->foo(*b);
// Sub::foo(*b);
return 0;
}
但是如果我用 nvcc
8.0 结合相同的主机编译器编译它,使用
nvcc -x cu -arch=sm_35 -c minimal.cc
我收到以下有趣的错误:
../minimal.cc: In function ‘int main(int, char**)’:
../minimal.cc:28:21: error: ‘internal::Base’ is an inaccessible base of ‘Sub’
如果将 Base
移出 internal
命名空间并移至全局命名空间,则会出现更具描述性的错误:
../minimal.cc: In function ‘int main(int, char**)’:
../minimal.cc:6:12: error: ‘class Base Base::Base’ is inaccessible
class Base
^
../minimal.cc:32:5: error: within this context
b->foo(*b);
^
../minimal.cc:32:11: error: ‘Base’ is an inaccessible base of ‘Sub’
b->foo(*b);
很明显,这似乎是由于使用指针调用静态方法的方式有点不标准,如果该行被注释掉的行替换,它编译得很好。
有人可以确认这是有效的 C++ 并因此是 nvcc
中的错误,还是 g++
不知何故仍然乐于接受的无效 C++?
我对此进行了更多研究,发现它确实是 nvcc
编译阶段之一的问题。使用 --save-temps
,并查看生成的 .cu.cpp.ii
文件,结果发现这一行
b->foo(*b);
被以下内容取代
(b->internal::Base::foo(*b));
这不会用 g++
编译,从那时起 foo
在 Sub
中导出为 public 的事实就丢失了。毕竟,这试图从 class 所在的 private
基址显式访问它。使用其他类型的调用 (Sub::foo
) 不会导致生成任何额外代码。
我断定这是 nvcc
中的错误。有趣的是,如果未在 Base
.
void foo(::Other &c)
,则此替换 不会 发生