【问题标题】:Template argument deduction for class templates in C++17: am I doing it wrong?C++17中类模板的模板参数推导:我做错了吗?
【发布时间】: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&lt;someType&gt; 或来自类 Derived2&lt;someType2&gt; 的对象)。这样,数组或vector&lt;Base *&gt; 可以存储指向各种派生类对象的指针。

GCC 只有 experimental support 用于 C++17,而且我无法访问其他编译器,所以虽然我收到编译错误,但我不确定我的代码是否错误。你怎么看?
我们如何动态决定pt_base 指向Derived&lt;someType&gt;Derived2&lt;someType2&gt; 中的一个对象(因此可以使用多态性)?

【问题讨论】:

  • 该错误消息声称不允许使用 Base *pt_base 中的 **pt_basedeclarator,但不是 declarator-id(例如未修饰的标识符)。不过,我在 N4687 的任何地方都找不到这条规则。
  • @aschepler 扣除规则只在某些地方生效。而original proposal 明确排除了指针、函数和引用等内容。
  • 另外,模板类推导发生在编译时。在您被允许 只写Base 的情况下,编译器将决定它实际上是指Base&lt;someType&gt; 还是什么。 Base 不是类型。因此,在运行时您不能在 Derived&lt;someType&gt;Derived&lt;someType2&gt; 上拥有单个变量点,除非它们实际上都继承了一些通用类型。您可能需要 std::anystd::variant 作为其 getValue() 的返回类型。
  • 如果vector&lt;Base*&gt; 有效,语言将直接支持类型擦除...
  • @Barry 那篇论文很容易成为我读过的最糟糕的书面采纳论文。但是,我并不是真正喜欢这整个“功能”。

标签: c++ templates g++ c++17


【解决方案1】:

类模板参数推导适用于声明类类型的实例:

Derived d(42);

或新表达式:

auto p = new Derived(42);

或函数式强制转换:

foo(Derived(42));

它不适用于声明指针。


您必须像以往一样简单地提供模板参数。或者,我猜:

template <class T> Base<T>* downcast(Base<T>* p) { return p; }
auto pt_base = downcast(new Derived(42));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    相关资源
    最近更新 更多