问题描述
我想为我的类型提供一个隐藏的朋友,并且同时在嵌入式名称空间中还有另一个具有相同名称的对象。一切正常类型都可以正常工作。
但是,如果我有模板,则在实例化模板时编译器会出错
redeFinition of 'cpo' as different kind of symbol
代码如下:
namespace lib{
struct CPO{
template<typename... T>
constexpr decltype(auto) operator()(T&&... args) const{
cpo(static_cast<T&&>(args)...);
}
};
inline namespace cpo_impl_{
inline constexpr CPO cpo{};
}
struct Foo1{
friend auto cpo(Foo1){
return 5;
}
};
template <typename T>
struct Foo2{
friend auto cpo(Foo2){
return 6;
}
};
}
int main(){
lib::Foo1 f1{};
lib::cpo(f1); // works fine;
lib::Foo2<int> f2{}; // error here
}
较小的示例在这里
namespace lib{
inline namespace impl_{
inline constexpr int foo = 5;
}
template <typename T>
struct Bar{
friend auto foo(Bar){
return 4;
}
};
}
int main(){
lib::bar<int> b{};
}
顺便说一句,我知道诸如tag_invoke
之类的其他技术,但是在这里我无法控制名称和库
解决方法
您的代码格式正确。这是Clang Bug 37556。
使用-std = c ++ 2a编译格式良好的程序:
from keras.utils import to_categorical def one_hot_encoding(seq): mp = dict(zip('ACGT',range(4))) seq_2_number = [mp[nucleotide] for nucleotide in seq] return to_categorical(seq_2_number,num_classes=4,dtype='int32').flatten()
产生诊断(https://godbolt.org/g/ceWLxY):
namespace X { inline namespace Y { int swap; } template<class> struct S { friend void swap(S&,S&) {} }; } int main() { X::S<int> s1,s2; swap(s1,s2); }
请注意,如果将S替换为a,则程序将成功编译 非模板类。关于CWG反射镜的讨论证实了这一点 程序格式良好,包括Richard的声明“糟糕,Clang的 模板实例化情况下的重新声明检查不正确 进行重新声明查找,就像在这里查找限定名称一样, 而不是重新声明查找不合格的名称。”
但是没有修复时间表。
作为解决方法,您可以将<source>:6:21: error: redefinition of 'swap' as different kind of symbol
friend void swap(S&,S&) {}
^
<source>:11:15: note: in instantiation of template class 'X::S<int>' requested here
X::S<int> s1,s2;
^
<source>:2:30: note: previous definition is here
inline namespace Y { int swap; }
^
1 error generated.
包裹在自己的Foo2
inline namespace
这应足以更改声明区域,以避免误诊。同时,名称查找应与命名空间不存在一样进行。