提问人:JohnB 提问时间:11/18/2012 最后编辑:JohnB 更新时间:11/18/2012 访问量:176
用于模板专用化的类似 Using-like 语句
Using-like statement for template specialization
问:
假设标头中有以下定义
namespace someNamespace {
template<class T, class S>
int operator + (const T & t, const S & s) {
return specialAdd (t, s);
}
}
现在我希望标头的用户能够执行类似
using someNamespace::operator + <OneClass,SecondClass>;
这显然是不可能的。
这样做的原因是我不希望我的运算符 + 干扰标准运算符 +,因此让用户可以指定应该定义哪些类型的运算符 +。有没有办法实现这一点?
答:
1赞
Yakk - Adam Nevraumont
11/18/2012
#1
他们可以专精打细算的类型特征类,并在运算符+中enable_if?将 operator+ 放在全局命名空间中,但它返回
std::enable_if< for::bar<c1>::value && for::bar<c2>::value, int >
其中 bar 是命名空间中的模板类型特征类,如下所示:
template<class T>
struct bar: std::false_type {};
我认为这应该导致 sfinae 使您的模板只与您专门接受的内容相匹配。
您可能希望将一些 deconst 和 ref 剥离放入该enable_if中,并在您的 operator+ 中进行一些完美的转发。
3赞
Martin
11/18/2012
#2
使用巴顿-纳克曼的技巧:http://en.wikipedia.org/wiki/Barton%E2%80%93Nackman_trick
template<typename T,typename S>
class AddEnabled{
friend int operator + (T const& t, const S & s) {
T temp(t);
return temp.add(s);
}
};
class MyClass: public AddEnabled<MyClass,int>{
public:
MyClass(int val):mVal(val){
}
int add(int s){
mVal+=s;
return mVal;
}
private:
int mVal;
};
下面是重载 << 运算符的另一个示例:
template<typename T>
class OutEnabled {
public:
friend std::ostream& operator<<(std::ostream& out, T const& val) {
return static_cast<OutEnabled<T> const&>(val).ioprint(out);
}
protected:
template<typename U>
U& ioprint(U& out) const {
return static_cast<T const*>(this)->print(out);
}
};
要使用它,您可以让类继承自 OutEnabled:
class MyClass: public OutEnabled<MyClass>{ ...
或者您可以定义一个 Sentry 对象,例如在 CPP 文件的匿名命名空间中
namespace{
OutEnabled<MyClass> sentry;
}
一旦模板 OutEnabled 实例化 (),GLOBAL 运算符就存在。OutEnabled<MyClass>
std::ostream& operator<<(std::ostream& out, MyClass const& val)
此外,MyClass 必须包含匹配的函数(模板)
template<typename U>
U& print(U& out) const {
out << mBottomLeft << "\t"<< mW << "\t"<< mH;
return out;
}
由于这被称为 .ioprint
该函数不是绝对必要的,但如果您没有在 中定义,它会为您提供更好的错误消息。U& ioprint(U& out)
print
MyClass
评论
0赞
JohnB
11/19/2012
谢谢你。这是一个非常好的解决方案。我假设不可能在“块”级别上实现这一点,即使运算符在某个代码块中定义,而不是在另一个代码块中定义,这是对的吗?(即 存在于代码中的某个地方,但在某个地方没有?operator + (C, D)
0赞
Martin
11/19/2012
@JohnB:这取决于你怎么说。如果您将匿名命名空间放在 cpp 中,则运算符将对此 cpp 有效,但恕我直言,没有其他任何意义。唉,我不完全确定,最简单的方法就是尝试一下。顺便说一句,为什么你只需要一个区块?
评论