Georg
Georg

Reputation: 1098

Template argument deduction for class templates in C++17: am I doing it wrong?

According to https://gcc.gnu.org/projects/cxx-status.html, version 7 of g++, used with flag -std=c++1z, supports template argument deduction for class templates.

I would expect the following code to compile, especially as Base is an abstract class, therefore:
1. the compiler knows no instance of Base can be created;
2. the pointer to base pt_base points to a clearly defined instance (i.e. Derived<int>{42}) where the type (int) is explicit.

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;
}

Yet, it does not compile. G++ complains that "template placeholder type 'Base' must be followed by a simple declarator-id"; if I understand correctly, it does not deduce the template argument.
It's a pity because I would like to dynamically decide which derived class pt_base points to (could be an object from class Derived<someType> or from class Derived2<someType2>). That way, an array or a vector<Base *> could store pointers to objects of various derived classes.

GCC only has experimental support for C++17 and I don't have access to another compiler, so although I get a compile error I am not sure my code is wrong. What do you think?
And how could we dynamically decide that pt_base points to an object from either Derived<someType> or Derived2<someType2> (so polymorphism can be used)?

Upvotes: 8

Views: 13296

Answers (1)

Barry
Barry

Reputation: 303890

Class template argument deduction works for declaring instances of class types:

Derived d(42);

Or new-expressions:

auto p = new Derived(42);

Or function-style casts:

foo(Derived(42));

It does not work for declaring pointers.


You'll have to simply provide the template arguments as you've always had to. Or, I guess:

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

Upvotes: 10

Related Questions