c – 在仅在某些情况下使用decltype的模板中实例化函数定义

作为理解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;
}

问题在于我不希望Wrapper暴露T可能无法实现的运算符.例如,如果T没有实现运算符,那么Wrapper也不应该公开运算符.

在运算符(和任何二元运算)的情况下,一切都运行,因为运算符必然成为模板函数,因此仅在我们尝试调用时实例化,例如Wrapper :: operator.

然而,在一元运算符(例如)的情况下,没有明确的方法来保护运算符,以便如果T实现运算符则实例化它.例如,这个类中的运算符的天真实现

auto operator++() -> decltype(++(*t)) {
    return ++(*t);
}

无法编译不支持operator()的T.

根据我对标准的理解,如果我们有以下使用Wrapper的代码

class X { };
Wrapper<X> w;

我们将实例化Wrapper和Wrapper :: operator()的声明,但不是它的定义,除非我们调用它(或显式实例化它).通常情况下这是可以的,因为X ::运算符的使用仅出现在Wrapper :: operator()的定义中.但是,由于decltype,我们在声明中使用X ::运算符,以便typechecker检查是否存在X ::运算符,从而失败.

我们可以定义operator()(通常是任何使用decltype的转发函数)和实例化的属性iff底层对象是否也支持operator()?或者给出模板实例化和decltype的语义,这是不可能完成的?

解决方法

您可以将运算符声明为非成员模板:
template <typename T>
auto operator++(Wrapper<T>& arg) -> decltype(++*arg.t) {
    return ++*arg.t;
}

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...