【发布时间】:2018-02-15 13:29:51
【问题描述】:
根据
https://gcc.gnu.org/projects/cxx-status.html,g++第7版,与标志-std=c++1z一起使用,支持类模板的模板参数推导。
我希望以下代码能够编译,尤其是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' 必须后跟一个简单的 declarator-id”;如果我理解正确,它不会推断出模板参数。
很遗憾,因为我想动态决定 pt_base 指向哪个派生类(可以是来自类 Derived<someType> 或来自类 Derived2<someType2> 的对象)。这样,数组或vector<Base *> 可以存储指向各种派生类对象的指针。
GCC 只有 experimental support 用于 C++17,而且我无法访问其他编译器,所以虽然我收到编译错误,但我不确定我的代码是否错误。你怎么看?
我们如何动态决定pt_base 指向Derived<someType> 或Derived2<someType2> 中的一个对象(因此可以使用多态性)?
【问题讨论】:
-
该错误消息声称不允许使用
Base *pt_base中的*。*pt_base是 declarator,但不是 declarator-id(例如未修饰的标识符)。不过,我在 N4687 的任何地方都找不到这条规则。 -
@aschepler 扣除规则只在某些地方生效。而original proposal 明确排除了指针、函数和引用等内容。
-
另外,模板类推导发生在编译时。在您被允许 只写
Base的情况下,编译器将决定它实际上是指Base<someType>还是什么。Base不是类型。因此,在运行时您不能在Derived<someType>或Derived<someType2>上拥有单个变量点,除非它们实际上都继承了一些通用类型。您可能需要std::any或std::variant作为其getValue()的返回类型。 -
如果
vector<Base*>有效,语言将直接支持类型擦除... -
@Barry 那篇论文很容易成为我读过的最糟糕的书面采纳论文。但是,我并不是真正喜欢这整个“功能”。