- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在处理我的 basic vector library 时,我一直在尝试使用一个很好的语法来进行基于 swizzle 的打印。尝试打印与所讨论 vector 不同维度的调配时会出现问题。在 GCC 4.0 中,我最初为每个 vector 中的每个维度都有 friend << 重载函数(有主体,即使它重复代码),这导致代码工作,即使从未实际调用非 native 维度代码.这在 GCC 4.2 中失败了。我最近意识到(愚蠢的我)只需要函数声明,而不是代码主体,所以我这样做了。现在我在 GCC 4.0 和 4.2 上都收到相同的警告:
LINE 50 warning: friend declaration 'std::ostream& operator<<(std::ostream&, const VECTOR3<TYPE>&)' declares a non-template function
加上其他函数声明的五个相同的警告。
下面的示例代码准确地展示了正在发生的事情,并包含重现问题所需的所有代码。
#include <iostream> // cout, endl
#include <sstream> // ostream, ostringstream, string
using std::cout;
using std::endl;
using std::string;
using std::ostream;
// Predefines
template <typename TYPE> union VECTOR2;
template <typename TYPE> union VECTOR3;
template <typename TYPE> union VECTOR4;
typedef VECTOR2<float> vec2;
typedef VECTOR3<float> vec3;
typedef VECTOR4<float> vec4;
template <typename TYPE>
union VECTOR2
{
private:
struct { TYPE x, y; } v;
struct s1 { protected: TYPE x, y; };
struct s2 { protected: TYPE x, y; };
struct s3 { protected: TYPE x, y; };
struct s4 { protected: TYPE x, y; };
struct X : s1 { operator TYPE() const { return s1::x; } };
struct XX : s2 { operator VECTOR2<TYPE>() const { return VECTOR2<TYPE>(s2::x, s2::x); } };
struct XXX : s3 { operator VECTOR3<TYPE>() const { return VECTOR3<TYPE>(s3::x, s3::x, s3::x); } };
struct XXXX : s4 { operator VECTOR4<TYPE>() const { return VECTOR4<TYPE>(s4::x, s4::x, s4::x, s4::x); } };
public:
VECTOR2() {}
VECTOR2(const TYPE& x, const TYPE& y) { v.x = x; v.y = y; }
X x;
XX xx;
XXX xxx;
XXXX xxxx;
// Overload for cout
friend ostream& operator<<(ostream& os, const VECTOR2<TYPE>& toString)
{
os << "(" << toString.v.x << ", " << toString.v.y << ")";
return os;
}
friend ostream& operator<<(ostream& os, const VECTOR3<TYPE>& toString);
friend ostream& operator<<(ostream& os, const VECTOR4<TYPE>& toString);
};
template <typename TYPE>
union VECTOR3
{
private:
struct { TYPE x, y, z; } v;
struct s1 { protected: TYPE x, y, z; };
struct s2 { protected: TYPE x, y, z; };
struct s3 { protected: TYPE x, y, z; };
struct s4 { protected: TYPE x, y, z; };
struct X : s1 { operator TYPE() const { return s1::x; } };
struct XX : s2 { operator VECTOR2<TYPE>() const { return VECTOR2<TYPE>(s2::x, s2::x); } };
struct XXX : s3 { operator VECTOR3<TYPE>() const { return VECTOR3<TYPE>(s3::x, s3::x, s3::x); } };
struct XXXX : s4 { operator VECTOR4<TYPE>() const { return VECTOR4<TYPE>(s4::x, s4::x, s4::x, s4::x); } };
public:
VECTOR3() {}
VECTOR3(const TYPE& x, const TYPE& y, const TYPE& z) { v.x = x; v.y = y; v.z = z; }
X x;
XX xx;
XXX xxx;
XXXX xxxx;
// Overload for cout
friend ostream& operator<<(ostream& os, const VECTOR3<TYPE>& toString)
{
os << "(" << toString.v.x << ", " << toString.v.y << ", " << toString.v.z << ")";
return os;
}
friend ostream& operator<<(ostream& os, const VECTOR2<TYPE>& toString);
friend ostream& operator<<(ostream& os, const VECTOR4<TYPE>& toString);
};
template <typename TYPE>
union VECTOR4
{
private:
struct { TYPE x, y, z, w; } v;
struct s1 { protected: TYPE x, y, z, w; };
struct s2 { protected: TYPE x, y, z, w; };
struct s3 { protected: TYPE x, y, z, w; };
struct s4 { protected: TYPE x, y, z, w; };
struct X : s1 { operator TYPE() const { return s1::x; } };
struct XX : s2 { operator VECTOR2<TYPE>() const { return VECTOR2<TYPE>(s2::x, s2::x); } };
struct XXX : s3 { operator VECTOR3<TYPE>() const { return VECTOR3<TYPE>(s3::x, s3::x, s3::x); } };
struct XXXX : s4 { operator VECTOR4<TYPE>() const { return VECTOR4<TYPE>(s4::x, s4::x, s4::x, s4::x); } };
public:
VECTOR4() {}
VECTOR4(const TYPE& x, const TYPE& y, const TYPE& z, const TYPE& w) { v.x = x; v.y = y; v.z = z; v.w = w; }
X x;
XX xx;
XXX xxx;
XXXX xxxx;
// Overload for cout
friend ostream& operator<<(ostream& os, const VECTOR4& toString)
{
os << "(" << toString.v.x << ", " << toString.v.y << ", " << toString.v.z << ", " << toString.v.w << ")";
return os;
}
friend ostream& operator<<(ostream& os, const VECTOR2<TYPE>& toString);
friend ostream& operator<<(ostream& os, const VECTOR3<TYPE>& toString);
};
// Test code
int main (int argc, char * const argv[])
{
vec2 my2dVector(1, 2);
cout << my2dVector.x << endl;
cout << my2dVector.xx << endl;
cout << my2dVector.xxx << endl;
cout << my2dVector.xxxx << endl;
vec3 my3dVector(3, 4, 5);
cout << my3dVector.x << endl;
cout << my3dVector.xx << endl;
cout << my3dVector.xxx << endl;
cout << my3dVector.xxxx << endl;
vec4 my4dVector(6, 7, 8, 9);
cout << my4dVector.x << endl;
cout << my4dVector.xx << endl;
cout << my4dVector.xxx << endl;
cout << my4dVector.xxxx << endl;
return 0;
}
代码工作并产生正确的输出,但我更喜欢尽可能没有警告的代码。我听从了编译器给我的建议(summarized here 并被论坛和 StackOverflow 描述为对这个警告的回答)并添加了两个据称可以告诉编译器发生了什么的事情。也就是说,我在模板 union 的预定义之后添加了函数定义作为非友元:
template <typename TYPE> ostream& operator<<(ostream& os, const VECTOR2<TYPE>& toString);
template <typename TYPE> ostream& operator<<(ostream& os, const VECTOR3<TYPE>& toString);
template <typename TYPE> ostream& operator<<(ostream& os, const VECTOR4<TYPE>& toString);
并且,对于导致问题的每个友元函数,我都添加了 <>
在函数名称之后,例如 VECTOR2 的情况:
friend ostream& operator<< <> (ostream& os, const VECTOR3<TYPE>& toString);
friend ostream& operator<< <> (ostream& os, const VECTOR4<TYPE>& toString);
但是,这样做会导致错误,例如:
LINE 139: error: no match for 'operator<<' in 'std::cout << my2dVector.VECTOR2<float>::xxx'
这是怎么回事?是与这些模板化的类似 union 类的结构如何相互关联有关,还是归因于 union 本身?
在重新思考涉及的问题并听取了Potatoswatter的各种建议后,我找到了最终的解决方案。与互联网上几乎每个 cout 重载示例不同,我不需要访问私有(private)成员信息,但可以使用公共(public)接口(interface)来执行我想做的事情。因此,我创建了一个非友元重载函数,该函数内联用于调用真正友元重载函数的调配部分。这绕过了编译器在模板化友元函数方面的问题。我已经添加到我的项目的最新版本中。它现在适用于我尝试过的两个版本的 GCC,没有任何警告。有问题的代码如下所示:
template <typename SWIZZLE> inline
typename EnableIf< Is2D< typename SWIZZLE::PARENT >, ostream >::type&
operator<<(ostream& os, const SWIZZLE& printVector)
{
os << (typename SWIZZLE::PARENT(printVector));
return os;
}
template <typename SWIZZLE> inline
typename EnableIf< Is3D< typename SWIZZLE::PARENT >, ostream >::type&
operator<<(ostream& os, const SWIZZLE& printVector)
{
os << (typename SWIZZLE::PARENT(printVector));
return os;
}
template <typename SWIZZLE> inline
typename EnableIf< Is4D< typename SWIZZLE::PARENT >, ostream >::type&
operator<<(ostream& os, const SWIZZLE& printVector)
{
os << (typename SWIZZLE::PARENT(printVector));
return os;
}
最佳答案
您不能声明免费 friend
仅在类模板中。除非在全局范围内明确声明,否则该定义在类外部不可见。 (编辑:这段代码是一个异常(exception); friend 们在 main
中被 ADL 找到。但是,我不明白为什么他们没有被 ADL 在其他模板中找到……)所以,例如,在关闭模板之后VECTOR2
的大括号, 添加原型(prototype)
template< class TYPE >
ostream& operator<<(ostream& os, const VECTOR2<TYPE>& toString);
除此之外,friend
你现在有因为裸原型(prototype)对我来说看起来没有必要。和 s1
至 s4
看起来显然是多余的。我无法辨别整件事的意图。
在这种情况下,免费的 friend
由于隐式转换的方式不能成为模板 operator
s被使用。所以上面的声明不会匹配 VECTOR
中的非模板声明。模板。通过友元机制由模板生成非模板函数是一种奇怪而棘手的语言特性,在这里可以正确使用,回旋余地很小。最好的选择是禁用警告,而不是尝试重构复杂的重载解决方案。
其实这里有一个简单的重构。只需添加 operator<<
到 swizzle 类以及隐式转换运算符。 (抱歉格式草率。)
#include <iostream> // cout, endl
#include <sstream> // ostream, ostringstream, string
using std::cout;
using std::endl;
using std::string;
using std::ostream;
// Predefines
template <typename TYPE> union VECTOR2;
template <typename TYPE> union VECTOR3;
template <typename TYPE> union VECTOR4;
typedef VECTOR2<float> vec2;
typedef VECTOR3<float> vec3;
typedef VECTOR4<float> vec4;
template< class TYPE2 >
ostream& operator<<(ostream& os, const VECTOR2<TYPE2>& toString)
{
os << "(" << toString.v.x << ", " << toString.v.y << ")";
return os;
}
template <typename TYPE>
union VECTOR2
{
private:
struct { TYPE x, y; } v;
struct s1 { protected: TYPE x, y; };
struct s2 { protected: TYPE x, y; };
struct s3 { protected: TYPE x, y; };
struct s4 { protected: TYPE x, y; };
struct X : s1 { operator TYPE() const { return s1::x; } };
struct XX : s2 { operator VECTOR2<TYPE>() const { return VECTOR2<TYPE>(s2::x, s2::x); }
friend ostream& operator<<( ostream &os, XX const &v ) { os << VECTOR2<TYPE>( v ); } };
struct XXX : s3 { operator VECTOR3<TYPE>() const { return VECTOR3<TYPE>(s3::x, s3::x, s3::x); }
friend ostream& operator<<( ostream &os, XXX const &v ) { os << VECTOR3<TYPE>( v ); } };
struct XXXX : s4 { operator VECTOR4<TYPE>() const { return VECTOR4<TYPE>(s4::x, s4::x, s4::x, s4::x); }
friend ostream& operator<<( ostream &os, XXXX const &v ) { os << VECTOR4<TYPE>( v ); } };
public:
VECTOR2() {}
VECTOR2(const TYPE& x, const TYPE& y) { v.x = x; v.y = y; }
X x;
XX xx;
XXX xxx;
XXXX xxxx;
// Overload for cout
friend ostream& operator<< <>(ostream& os, const VECTOR2<TYPE>& toString);
};
template< class TYPE >
ostream& operator<<(ostream& os, const VECTOR3<TYPE>& toString)
{
os << "(" << toString.v.x << ", " << toString.v.y << ", " << toString.v.z << ")";
return os;
}
template <typename TYPE>
union VECTOR3
{
private:
struct { TYPE x, y, z; } v;
struct s1 { protected: TYPE x, y, z; };
struct s2 { protected: TYPE x, y, z; };
struct s3 { protected: TYPE x, y, z; };
struct s4 { protected: TYPE x, y, z; };
struct X : s1 { operator TYPE() const { return s1::x; } };
struct XX : s2 { operator VECTOR2<TYPE>() const { return VECTOR2<TYPE>(s2::x, s2::x); }
friend ostream& operator<<( ostream &os, XX const &v ) { os << VECTOR2<TYPE>( v ); } };
struct XXX : s3 { operator VECTOR3<TYPE>() const { return VECTOR3<TYPE>(s3::x, s3::x, s3::x); }
friend ostream& operator<<( ostream &os, XXX const &v ) { os << VECTOR3<TYPE>( v ); } };
struct XXXX : s4 { operator VECTOR4<TYPE>() const { return VECTOR4<TYPE>(s4::x, s4::x, s4::x, s4::x); }
friend ostream& operator<<( ostream &os, XXXX const &v ) { os << VECTOR4<TYPE>( v ); } };
public:
VECTOR3() {}
VECTOR3(const TYPE& x, const TYPE& y, const TYPE& z) { v.x = x; v.y = y; v.z = z; }
X x;
XX xx;
XXX xxx;
XXXX xxxx;
// Overload for cout
friend ostream& operator<< <>(ostream& os, const VECTOR3<TYPE>& toString);
};
template< class TYPE >
ostream& operator<<(ostream& os, const VECTOR4<TYPE>& toString)
{
os << "(" << toString.v.x << ", " << toString.v.y << ", " << toString.v.z << ", " << toString.v.w << ")";
return os;
}
template <typename TYPE>
union VECTOR4
{
private:
struct { TYPE x, y, z, w; } v;
struct s1 { protected: TYPE x, y, z, w; };
struct s2 { protected: TYPE x, y, z, w; };
struct s3 { protected: TYPE x, y, z, w; };
struct s4 { protected: TYPE x, y, z, w; };
struct X : s1 { operator TYPE() const { return s1::x; } };
struct XX : s2 { operator VECTOR2<TYPE>() const { return VECTOR2<TYPE>(s2::x, s2::x); }
friend ostream& operator<<( ostream &os, XX const &v ) { os << VECTOR2<TYPE>( v ); } };
struct XXX : s3 { operator VECTOR3<TYPE>() const { return VECTOR3<TYPE>(s3::x, s3::x, s3::x); }
friend ostream& operator<<( ostream &os, XXX const &v ) { os << VECTOR3<TYPE>( v ); } };
struct XXXX : s4 { operator VECTOR4<TYPE>() const { return VECTOR4<TYPE>(s4::x, s4::x, s4::x, s4::x); }
friend ostream& operator<<( ostream &os, XXXX const &v ) { os << VECTOR4<TYPE>( v ); } };
public:
VECTOR4() {}
VECTOR4(const TYPE& x, const TYPE& y, const TYPE& z, const TYPE& w) { v.x = x; v.y = y; v.z = z; v.w = w; }
X x;
XX xx;
XXX xxx;
XXXX xxxx;
// Overload for cout
friend ostream& operator<< <>(ostream& os, const VECTOR4& toString);
};
// Test code
int main (int argc, char * const argv[])
{
vec2 my2dVector(1, 2);
cout << my2dVector.x << endl;
cout << my2dVector.xx << endl;
cout << my2dVector.xxx << endl;
cout << my2dVector.xxxx << endl;
vec3 my3dVector(3, 4, 5);
cout << my3dVector.x << endl;
cout << my3dVector.xx << endl;
cout << my3dVector.xxx << endl;
cout << my3dVector.xxxx << endl;
vec4 my4dVector(6, 7, 8, 9);
cout << my4dVector.x << endl;
cout << my4dVector.xx << endl;
cout << my4dVector.xxx << endl;
cout << my4dVector.xxxx << endl;
return 0;
}
很奇怪,我添加的函数是仍然是在模板中定义的非模板 friend ,与我删除的函数非常相似。但无论出于何种原因,GCC 都不会提示它们。如果是这样,您可以使它们成为模板并将它们移到适当的命名空间范围之外。
顺便说一下,与原始代码相比,我个人并不喜欢此代码。如果我是你,我只会禁用警告。
关于c++ - 模板化 << friend 在与其他模板化 union 类型相互关联时不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3489619/
我想知道将来对我来说最简单的方法是什么,可以使查询既有效又不那么复杂。 我应该像这样保存双向关系吗 from_id=1, to_id=2from_id=2, to_id=1 或者只创建一个唯一的行 f
假设您有一个拥有十亿用户的社交网络。在每个用户的页面上,您想要显示该用户的 friend 数、 friend 的 friend 等等,最多五度。友谊是相互的。计数不需要立即更新,但它们应该是精确的。
public void notMyFriend(Student student1) { System.out.println("Friends who are not my frien
我有如下3个表格 用户 - id integer primary_key - user_name friend - id autoincrement primary_key - user1 integ
如何从 Friends 表中获取 friend 列表以及我 friend 的 friend 数(不包括我的 friend 数) friend 表"tbl_users_friends 字段 1:id字段
我的 MySQL 表结构是这样的。 USER int id varchar username FRIEND_LIST int user_id int friend_id 对于每个 friend 关系,
假设 a,b,c 和 b,d,e 和 c,f,g 和 a,e,g,h 是 friend 。所以 获取共同好友 b/w a&b: MATCH (me:User {username:'a'}) -[r:F
我正在开发“可能的 friend ”功能。我需要显示所有不是我 friend 的 friend 的 friend ,也不要发送我或没有我的待处理请求 FRIENDSHIPS user_id frien
如果两个用户是 friend ,我在“ friend ”表中有一个条目,如下所示: table: friends ------------------------ uid1
我有一个 friend 表,用于跟踪数据库中的关系 - 我将一个查询与子查询放在一起,该子查询从 friend 的 friend 那里获取个人资料信息 我的 friend 表如下所示 - id 双向出
我想结交 friend 的 friend 的 friend 。我得到了结果,但我不确定我的查询是否正确。我正在使用嵌套选择。 我的问题是: 查询是否正确? 我如何使用 join 执行此查询? 这是我的
假设我有一个包含 friend 属性的用户对象。这个 friends 属性是其他用户对象的数组,因此是你的 friend 。找到你 friend 的 friend 但不是你 friend 的最快算法是
我想结交我的 friend 以及 friend 的 friend ,但仅限于二级 friend 我的表结构是这样的 user_id friend_user_id 1 2 1
为了了解使用 Neo4J 建立 friend 关系的优势,我在 MySQL 数据库上创建了一张用于 Persons 的表(“Persons”,20900 个数据集): id | name --
假设我有一个名为“ friend ”的表,对于每个友谊,我添加两个条目。例如,如果用户 1 和 2 是 friend ,我们将有: uid1 uid2 ---------- 1 2 2 1
在我的图形数据库中,我有 Twig 和树叶。分支可以“包含”叶子,分支可以“包含”分支。 如何使用 Gremlin 找到与给定分支直接或间接相关的所有叶子? 我让这个在 Cypher 中工作: STA
我正在尝试使用 iPhone Facebook SDK 获取我 friend 的 friend 列表。我尝试了一种使用 FQL 和 Graph API 的方法,但在这两种情况下我都遇到了错误: "Ca
我有这个 MySQL 表: 假设我以用户 1 的身份登录,正在浏览用户 2 的个人资料。由于我们是共同的 friend (1 是 2 的 friend ,2 是 1 的 friend ),我需要回应“
我想得到我 friend 的 friend 不是我 friend 的 friend 。我有一张这样的 table :用户 friend (idUser,idUserFriend) 我在想这样的事情:
我有这个 Cypher 查询... match (p:Person{userid:8432})-[r:friends_with]->(p1:Person)-[r2:friends_with]->(p2
我是一名优秀的程序员,十分优秀!