重载运算符“<<”的使用不明确
Use of overloaded operator '<<' is ambiguous
我正在编写一个 class float32x4_t
来模仿 x86 平台上的 ARM NEON 数据类型。它的对象中有4个元素。
我想 cout
一个 float32x4_t
实例(打印出逗号分隔的 4 个元素),但我的重载函数无法编译。
我的代码是:
#include <iostream>
struct float32x4_t
{
float val[4];
float& operator [] (int i) {
return val[i];
}
const float& operator [] (int i) const {
return val[i];
}
int size() const {
return 4;
}
};
template<class T>
std::ostream & operator << (std::ostream & os, const T& v)
{
for (int i=0; i<v.size(); i++) {
os << v.val[i] << ", ";
}
os << std::endl;
return os;
}
/// @ingroup add
/// r[i] = a[i] + b[i]
static inline float32x4_t vaddq_f32(float32x4_t a, float32x4_t b)
{
float32x4_t r;
for (int i=0; i<4; i++) {
r[i] = a[i] + b[i];
}
return r;
}
#include <stdio.h>
int main(int argc, char** argv)
{
float32x4_t v1 = { 1.0, 2.0, 3.0, 4.0 };
float32x4_t v2 = { 1.0, 1.0, 1.0, 1.0 };
float32x4_t sum = vaddq_f32(v1, v2);
std::cout << sum << std::endl;
return 0;
}
整个错误如下:
/home/zz/work/neon_pedal/neon_pedal.h:25:24: error: use of overloaded operator '<<' is ambiguous (with operand types 'std::basic_ostream<char>::__ostream_type' (aka 'basic_ostream<char>') and 'const char [3]')
os << v.val[i] << ", ";
~~~~~~~~~~~~~~ ^ ~~~~
/home/zz/work/neon_pedal/main.cpp:18:15: note: in instantiation of function template specialization 'operator<<<float32x4_t>' requested here
std::cout << sum << std::endl;
^
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ostream:565:5: note: candidate function [with _Traits = std::char_traits<char>]
operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
^
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ostream:548:5: note: candidate function [with _CharT = char, _Traits = std::char_traits<char>]
operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s)
^
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/ostream.tcc:321:5: note: candidate function [with _CharT = char, _Traits = std::char_traits<char>]
operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s)
^
/home/zz/work/neon_pedal/neon_pedal.h:22:16: note: candidate function [with T = char [3]]
std::ostream & operator << (std::ostream & os, const T& v)
如何解决这个编译错误?
注意:这里重载的 operator <<
是带模板的,那是因为将不仅仅是 float32x4_t
类型。会有如float32x2_t
、int8x8_t
、int16x8_t
等
您的模板 operator <<
正在尝试为 所有内容 提供重载;不仅仅是你的类型(结果是意外的匹配是模棱两可的)。
有很多方法可以解决这个问题,但由于您已经定义了自己的类型,并且这样做的整体目标是尽量减少必须编写的 operator <<
重载的数量才能匹配,请考虑一个通用的 TxN模板,为此编写一个(单一的)重载,然后将您的真实类型作为自然演变的别名。
#include <iostream>
#include <array>
template<class T, size_t N = 4>
struct TxN
{
T val[N];
TxN() = default;
T& operator[](size_t i)
{
return val[i];
}
T const& operator[](size_t i) const
{
return val[i];
}
size_t size() const
{
return N;
}
// there are at least three different ways to do this operator, but
// this is the easiest, so I included below.
friend std::ostream& operator <<(std::ostream& os, TxN<T,N> const& t)
{
os << t.val[0];
for (size_t i=1; i<N; ++i)
os << ',' << t.val[i];
return os;
}
};
// now creating TypeN shrouds is trivial.
using float32x4_t = TxN<float, 4>;
using int16x8_t = TxN<short,8>;
/// @ingroup add
/// r[i] = a[i] + b[i]
static inline float32x4_t vaddq_f32(float32x4_t a, float32x4_t b)
{
float32x4_t r;
for (int i=0; i<4; i++) {
r[i] = a[i] + b[i];
}
return r;
}
int main(int argc, char** argv)
{
float32x4_t v1 = { 1.0, 2.0, 3.0, 4.0 };
float32x4_t v2 = { 1.0, 1.0, 1.0, 1.0 };
float32x4_t sum = vaddq_f32(v1, v2);
std::cout << sum << '\n';
int16x8_t i0 = { 1,2,3,4,5,6,7,8 };
std::cout << i0 << '\n';
return 0;
}
输出
2,3,4,5
1,2,3,4,5,6,7,8
您正在尝试为所有类型重载 <<
运算符。因此,如果 <<
运算符已经在 std 命名空间中重载了一种类型,那么它将是模棱两可的,因为编译器不知道选择哪一个,您的重载还是 std 命名空间中的那个。
for (int i=0; i<v.size(); i++) {
os << v.val[i] << ", ";
}
具体来说,const char[] = ", "
导致了这个问题,因为在 std 命名空间中已经存在过载。请注意,您还打电话
os << std::endl
但您在 std::
中是明确的,因此没有歧义。如果你想使用 std
命名空间中存在的 ostream
重载,我假设你这样做,那么就没有办法使你的模板化重载可行。
您可以在您的结构中声明一个友元重载。
friend std::ostream & operator << (std::ostream & os,const float32x4_t & self){
...
}
我正在编写一个 class float32x4_t
来模仿 x86 平台上的 ARM NEON 数据类型。它的对象中有4个元素。
我想 cout
一个 float32x4_t
实例(打印出逗号分隔的 4 个元素),但我的重载函数无法编译。
我的代码是:
#include <iostream>
struct float32x4_t
{
float val[4];
float& operator [] (int i) {
return val[i];
}
const float& operator [] (int i) const {
return val[i];
}
int size() const {
return 4;
}
};
template<class T>
std::ostream & operator << (std::ostream & os, const T& v)
{
for (int i=0; i<v.size(); i++) {
os << v.val[i] << ", ";
}
os << std::endl;
return os;
}
/// @ingroup add
/// r[i] = a[i] + b[i]
static inline float32x4_t vaddq_f32(float32x4_t a, float32x4_t b)
{
float32x4_t r;
for (int i=0; i<4; i++) {
r[i] = a[i] + b[i];
}
return r;
}
#include <stdio.h>
int main(int argc, char** argv)
{
float32x4_t v1 = { 1.0, 2.0, 3.0, 4.0 };
float32x4_t v2 = { 1.0, 1.0, 1.0, 1.0 };
float32x4_t sum = vaddq_f32(v1, v2);
std::cout << sum << std::endl;
return 0;
}
整个错误如下:
/home/zz/work/neon_pedal/neon_pedal.h:25:24: error: use of overloaded operator '<<' is ambiguous (with operand types 'std::basic_ostream<char>::__ostream_type' (aka 'basic_ostream<char>') and 'const char [3]')
os << v.val[i] << ", ";
~~~~~~~~~~~~~~ ^ ~~~~
/home/zz/work/neon_pedal/main.cpp:18:15: note: in instantiation of function template specialization 'operator<<<float32x4_t>' requested here
std::cout << sum << std::endl;
^
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ostream:565:5: note: candidate function [with _Traits = std::char_traits<char>]
operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
^
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ostream:548:5: note: candidate function [with _CharT = char, _Traits = std::char_traits<char>]
operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s)
^
/usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/ostream.tcc:321:5: note: candidate function [with _CharT = char, _Traits = std::char_traits<char>]
operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s)
^
/home/zz/work/neon_pedal/neon_pedal.h:22:16: note: candidate function [with T = char [3]]
std::ostream & operator << (std::ostream & os, const T& v)
如何解决这个编译错误?
注意:这里重载的 operator <<
是带模板的,那是因为将不仅仅是 float32x4_t
类型。会有如float32x2_t
、int8x8_t
、int16x8_t
等
您的模板 operator <<
正在尝试为 所有内容 提供重载;不仅仅是你的类型(结果是意外的匹配是模棱两可的)。
有很多方法可以解决这个问题,但由于您已经定义了自己的类型,并且这样做的整体目标是尽量减少必须编写的 operator <<
重载的数量才能匹配,请考虑一个通用的 TxN模板,为此编写一个(单一的)重载,然后将您的真实类型作为自然演变的别名。
#include <iostream>
#include <array>
template<class T, size_t N = 4>
struct TxN
{
T val[N];
TxN() = default;
T& operator[](size_t i)
{
return val[i];
}
T const& operator[](size_t i) const
{
return val[i];
}
size_t size() const
{
return N;
}
// there are at least three different ways to do this operator, but
// this is the easiest, so I included below.
friend std::ostream& operator <<(std::ostream& os, TxN<T,N> const& t)
{
os << t.val[0];
for (size_t i=1; i<N; ++i)
os << ',' << t.val[i];
return os;
}
};
// now creating TypeN shrouds is trivial.
using float32x4_t = TxN<float, 4>;
using int16x8_t = TxN<short,8>;
/// @ingroup add
/// r[i] = a[i] + b[i]
static inline float32x4_t vaddq_f32(float32x4_t a, float32x4_t b)
{
float32x4_t r;
for (int i=0; i<4; i++) {
r[i] = a[i] + b[i];
}
return r;
}
int main(int argc, char** argv)
{
float32x4_t v1 = { 1.0, 2.0, 3.0, 4.0 };
float32x4_t v2 = { 1.0, 1.0, 1.0, 1.0 };
float32x4_t sum = vaddq_f32(v1, v2);
std::cout << sum << '\n';
int16x8_t i0 = { 1,2,3,4,5,6,7,8 };
std::cout << i0 << '\n';
return 0;
}
输出
2,3,4,5
1,2,3,4,5,6,7,8
您正在尝试为所有类型重载 <<
运算符。因此,如果 <<
运算符已经在 std 命名空间中重载了一种类型,那么它将是模棱两可的,因为编译器不知道选择哪一个,您的重载还是 std 命名空间中的那个。
for (int i=0; i<v.size(); i++) {
os << v.val[i] << ", ";
}
具体来说,const char[] = ", "
导致了这个问题,因为在 std 命名空间中已经存在过载。请注意,您还打电话
os << std::endl
但您在 std::
中是明确的,因此没有歧义。如果你想使用 std
命名空间中存在的 ostream
重载,我假设你这样做,那么就没有办法使你的模板化重载可行。
您可以在您的结构中声明一个友元重载。
friend std::ostream & operator << (std::ostream & os,const float32x4_t & self){
...
}