根据 https://gcc.gnu.org/projects/cxx-status.html,g ++的版本7与标记-std=c++1z
一起使用,支持类模板的模板参数推导。C++中类模板的模板参数推导17:我做错了吗?
我希望下面的代码进行编译,特别是作为Base
是一个抽象类,因此:
1.编译器知道没有的Base
实例可被创建的;
2.指向基地pt_base
的指针指向明确定义的实例(即Derived<int>{42}
),其中类型(int
)是明确的。
template<typename ValueType>
class Base {
public:
virtual ValueType getValue() = 0;
};
template<typename ValueType>
class Derived : public Base<ValueType>{
public:
Derived(ValueType argt){ value = argt; }
virtual ValueType getValue(){ return value; }
ValueType value;
};
int main(){
Base *pt_base = new(Derived<int>{42}); // *ERROR*
delete pt_base;
}
然而,它does not compile。 G ++抱怨“模板占位符类型”Base“后面必须跟一个简单的声明符号”;如果我理解正确,它不会推导出模板参数。
很遗憾,因为我想动态地决定哪个派生类pt_base
指向(可能是来自类Derived<someType>
或类Derived2<someType2>
的对象)。这样,数组或vector<Base *>
可以存储指向各种派生类的对象的指针。
对于C++ 17,GCC只有experimental support,并且我没有访问其他编译器的权限,所以尽管我收到编译错误,但我不确定我的代码是否有错。你怎么看?
我们如何动态地决定pt_base
指向Derived<someType>
或Derived2<someType2>
(因此可以使用多态性)的对象?
该错误消息声明'Base * pt_base'中的'*'是不允许的。 '* pt_base'是一个_declarator_,但不是_declarator-id_(比如一个未修饰的标识符)。不过,我无法在N4687的任何地方找到这条规则。 – aschepler
@aschepler演绎规则只是在某些地方进行。 [原始提案](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html)明确排除了诸如指针,函数和引用之类的内容。 – Barry
此外,模板类扣除发生在编译时。在你被允许编写'Base'的情况下,编译器会决定它是否实际上意味着'Base'或其他什么。 'Base'不是一种类型。因此,在运行时,您不能在“派生的”或“派生的”上有单个变量点,除非它们实际上都继承了一些常见类型。您可能需要一个'std :: any'或'std :: variant'作为其''getValue()'的返回类型。 –
aschepler