在模板 class 中声明 non-template 函数?
Declare non-template function in a template class?
NOTE: this post is different from this one: Declare non-template friend function for template class outside the class, so please read my question before marking it as duplicate.
我想在 class 模板中声明一个 non-template 友元函数,该友元函数的参数和 return 类型 无关 到模板参数。我应该怎么做?
请注意它与之前的问题不同,因为在那个问题中,那个友元函数的参数和return类型是相关的 到模板参数。
示例,改编自上述问题:
// class.h
#include <iostream>
using namespace std;
template <typename T>
struct B
{
T value;
int value2;
B() : value2(1) {}
friend void modify(const int&); // unrelated to T!
void printValue2() {
modify(value2);
cout << value2 << endl;
}
};
// define friend function foo() in a class.cpp file, not in the header
void modify(const int &v) { v = v * 2 + 1; } // HOW should I write it?
// main.cpp
int main() {
B<int> b;
b.printValue2();
return 0;
}
我知道我可以在这个模板外声明 modify()
class,这样它就变成了普通的普通函数。但我只希望此模板 class 可以访问 modify()
。或者,为了实现访问控制的这一目标,我可以将 modify()
定义为此模板 class 中的静态方法,但这会使该方法成为模板方法,迫使我将其定义在 header.
跟进:如果上面的朋友方法不行,我应该如何同时实现两个目标:
- 访问控制:只有class模板可以访问
modify()
- 能够在 *.cpp 文件中定义
modify()
,而不是在 header. 中
已接受答案:
要实现上述两个目标,请不要滥用友谊。
最好的做法是让class模板私下继承一个non-template基础class,并在那个基础class 声明与模板参数无关的通用 non-template 方法。
因此,您可以在单独的 *.cpp 文件中定义这些方法,从而减小 header 的大小。
你这样做:
// class.cpp
void modify(const int &v) { v = v * 2 + 1; }
你实际上是在滥用友谊,但是没关系。这意味着您需要解决使用 friend
声明函数的含义:它仅通过 ADL 可见!现在 没有 方式来引用 modify
,因为 modify
不依赖于 B
,所以 B
的作用域从未搜索名为 modify
.
的函数
有一个解决方法,但不是很好。您需要在每个使用它的函数中声明 modify
。您也可以在全局范围内声明它,然后每个人都可以调用它。或者,您始终可以在 detail
命名空间中声明它(但这有点相同的问题):
template<typename T>
void B<T>::printValue2() {
void modify(const int&);
modify(value2);
cout << value2 << endl;
}
正如我在评论中所说,friend
ship 控制对 class 的访问。只要你的函数 modify()
是一个独立的函数,它就不能成为好友。因为您想从模板中调用它,所以它也不能隐藏在 .cpp 文件中,但必须在 class 模板 B 及其成员使用 modify()
.[= 的定义中可见。 17=]
一个解决方案是将 modify
作为 static
方法放在辅助非模板 class 中,这反过来与模板 B<>
.[=17 成为朋友=]
// file foo.h (header)
namespace foo {
template<typename> class B; // forward declaration
class exclusive_for_B
{
template<typename T>
friend class B<T>;
static void modify(int&x) // must take int&, not const int&
{ x &= x+42; }
};
template<typename T>
class B
{
int val;
public:
...
void printvalue()
{
exclusive_for_B::modify(val); // access via friendship
std::cout << val << '\n';
}
};
}
您可能会使用私有继承而不是友谊:
// class.h
#include <iostream>
class B_helper
{
protected:
static void modify(int &v);
};
template <typename T>
struct B : private B_helper
{
T value;
int value2;
B() : value2(1) {}
void printValue2() {
modify(value2);
std::cout << value2 << std::endl;
}
};
// class.cpp
void B_helper::modify(int &v) { v = v * 2 + 1; }
NOTE: this post is different from this one: Declare non-template friend function for template class outside the class, so please read my question before marking it as duplicate.
我想在 class 模板中声明一个 non-template 友元函数,该友元函数的参数和 return 类型 无关 到模板参数。我应该怎么做?
请注意它与之前的问题不同,因为在那个问题中,那个友元函数的参数和return类型是相关的 到模板参数。
示例,改编自上述问题:
// class.h
#include <iostream>
using namespace std;
template <typename T>
struct B
{
T value;
int value2;
B() : value2(1) {}
friend void modify(const int&); // unrelated to T!
void printValue2() {
modify(value2);
cout << value2 << endl;
}
};
// define friend function foo() in a class.cpp file, not in the header
void modify(const int &v) { v = v * 2 + 1; } // HOW should I write it?
// main.cpp
int main() {
B<int> b;
b.printValue2();
return 0;
}
我知道我可以在这个模板外声明 modify()
class,这样它就变成了普通的普通函数。但我只希望此模板 class 可以访问 modify()
。或者,为了实现访问控制的这一目标,我可以将 modify()
定义为此模板 class 中的静态方法,但这会使该方法成为模板方法,迫使我将其定义在 header.
跟进:如果上面的朋友方法不行,我应该如何同时实现两个目标:
- 访问控制:只有class模板可以访问
modify()
- 能够在 *.cpp 文件中定义
modify()
,而不是在 header. 中
已接受答案:
要实现上述两个目标,请不要滥用友谊。
最好的做法是让class模板私下继承一个non-template基础class,并在那个基础class 声明与模板参数无关的通用 non-template 方法。
因此,您可以在单独的 *.cpp 文件中定义这些方法,从而减小 header 的大小。
你这样做:
// class.cpp
void modify(const int &v) { v = v * 2 + 1; }
你实际上是在滥用友谊,但是没关系。这意味着您需要解决使用 friend
声明函数的含义:它仅通过 ADL 可见!现在 没有 方式来引用 modify
,因为 modify
不依赖于 B
,所以 B
的作用域从未搜索名为 modify
.
有一个解决方法,但不是很好。您需要在每个使用它的函数中声明 modify
。您也可以在全局范围内声明它,然后每个人都可以调用它。或者,您始终可以在 detail
命名空间中声明它(但这有点相同的问题):
template<typename T>
void B<T>::printValue2() {
void modify(const int&);
modify(value2);
cout << value2 << endl;
}
正如我在评论中所说,friend
ship 控制对 class 的访问。只要你的函数 modify()
是一个独立的函数,它就不能成为好友。因为您想从模板中调用它,所以它也不能隐藏在 .cpp 文件中,但必须在 class 模板 B 及其成员使用 modify()
.[= 的定义中可见。 17=]
一个解决方案是将 modify
作为 static
方法放在辅助非模板 class 中,这反过来与模板 B<>
.[=17 成为朋友=]
// file foo.h (header)
namespace foo {
template<typename> class B; // forward declaration
class exclusive_for_B
{
template<typename T>
friend class B<T>;
static void modify(int&x) // must take int&, not const int&
{ x &= x+42; }
};
template<typename T>
class B
{
int val;
public:
...
void printvalue()
{
exclusive_for_B::modify(val); // access via friendship
std::cout << val << '\n';
}
};
}
您可能会使用私有继承而不是友谊:
// class.h
#include <iostream>
class B_helper
{
protected:
static void modify(int &v);
};
template <typename T>
struct B : private B_helper
{
T value;
int value2;
B() : value2(1) {}
void printValue2() {
modify(value2);
std::cout << value2 << std::endl;
}
};
// class.cpp
void B_helper::modify(int &v) { v = v * 2 + 1; }