在Java规范(http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9)中,new具有以下形式:
ClassInstanceCreationExpression ::=
| new TypeArguments_opt TypeDeclSpecifier TypeArgumentsOrDiamond_opt
( ArgumentListopt ) ClassBodyopt
| Primary . new TypeArguments_opt Identifier TypeArgumentsOrDiamond_opt
( ArgumentListopt ) ClassBodyopt
Run Code Online (Sandbox Code Playgroud)
新的后面的第一个可选类型参数列表的目的是什么?我无法从我对15.9节的阅读中找到它(对类型参数列表的所有引用似乎都引用了类型/标识符之后的列表).测试标准Java编译器上的随机位会产生令人困惑的结果:
public class Foo<T> { }
// ...
Foo<Integer> t1 = new <Integer> Foo<Integer>(); // works
Foo<Integer> t2 = new <Integer> Foo(); // works -- unchecked warning missing the type arg after Foo
Foo<Integer> t3 = new <Boolean> Foo<Integer>(); // works
Foo<Integer> t4 = new <Float, Boolean> Foo<Integer>(); // works
Foo<Integer> t5 = new <NotDefined> …Run Code Online (Sandbox Code Playgroud) 作为理解C++ 0x的练习,我试图创建一个C++类,它包含一些模板化类型的指针:
template <typename T>
class Wrapper {
T *t;
/* ... */
};
Run Code Online (Sandbox Code Playgroud)
在Wrapper类中,我想公开T可以通过Wrapper类实现的任何重载操作符.包装器本身只是将函数调用转发给底层的t对象.
template <typename U>
auto operator+(U &u) -> decltype (*t + u) {
return *t + u;
}
Run Code Online (Sandbox Code Playgroud)
问题在于我不希望Wrapper暴露T可能无法实现的操作员.例如,如果T没有实现operator +,那么Wrapper也不应该公开operator +.
在operator +(以及任何二进制操作)的情况下,一切都运行,因为运算符必然成为模板函数,因此仅在我们尝试调用时实例化,例如,Wrapper :: operator +.
然而,在一元运算符(例如,++)的情况下,没有一种明确的方法来保护运算符,以便在tf实现operator ++时实例化它.例如,这个类中的operator ++的天真实现
auto operator++() -> decltype(++(*t)) {
return ++(*t);
}
Run Code Online (Sandbox Code Playgroud)
无法为不支持operator ++()的T编译.
根据我对标准的理解,如果我们有以下使用Wrapper的代码
class X { };
Wrapper<X> w;
Run Code Online (Sandbox Code Playgroud)
我们将实例化Wrapper和Wrapper :: operator ++()的声明,但不是它的定义,除非我们调用它(或显式地实例化它).通常情况下这是可以的,因为X :: operator ++的使用仅出现在Wrapper :: operator ++()的定义中.但是,由于decltype,我们在声明中使用X :: operator ++,以便typechecker检查是否存在X :: operator ++,从而失败. …