作为理解C++ 0x的练习,我试图创建一个C++类,该类包装一些模板化类型的指针:
template <typename T>
class Wrapper {
T *t;
/* ... */
};
在Wrapper类内部,我想公开T可能通过Wrapper类实现的所有重载运算符。包装器本身只是将函数调用转发到基础的t对象。
template <typename U>
auto operator+(U &u) -> decltype (*t + u) {
return *t + u;
}
问题是我不希望包装程序公开T可能没有实现的运算符。例如,如果T没有实现operator +,则包装器也不应公开operator +。
对于operator +(以及任何二进制运算),一切都会进行,因为该运算符必定成为模板函数,因此仅在我们尝试调用例如Wrapper::operator +时才实例化。
但是,对于一元运算符(例如++),没有明确的方法来保护该运算符,以便在T实现operator++时实例化它。例如,此类中的operator++的天真的实现
auto operator++() -> decltype(++(*t)) {
return ++(*t);
}
无法为不支持operator++()的T进行编译。
根据我对标准的理解,如果我们有使用Wrapper的以下代码
class X { };
Wrapper<X> w;
我们将实例化Wrapper和Wrapper::operator++()的声明,但不会实例化其定义,除非我们调用它(或显式实例化它)。通常这是可以的,因为仅在Wrapper::operator++()的定义中才使用X::operator++。但是,由于使用了decltype,我们在声明中使用X::operator++,以便类型检查器检查X::operator++的存在并因此失败。
我们是否可以定义operator++()(以及通常使用decltype的任何此类转发函数),使其具有被实例化的属性,前提是基础对象也支持operator++()?还是给定模板实例化和decltype的语义,这是不可能完成的吗?
最佳答案
您可以将运算符声明为非成员模板:
template <typename T>
auto operator++(Wrapper<T>& arg) -> decltype(++*arg.t) {
return ++*arg.t;
}
关于c++ - 仅在某些情况下实例化使用decltype的模板中的函数定义,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5503605/