Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)?

like image 638
Georg Avatar asked Sep 06 '17 23:09

Georg


People also ask

What is template argument deduction?

Template argument deduction is used in declarations of functions, when deducing the meaning of the auto specifier in the function's return type, from the return statement.

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

Can there be more than one argument to template?

Can there be more than one argument to templates? Yes, like normal parameters, we can pass more than one data type as arguments to templates.

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.


1 Answers

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));
like image 196
Barry Avatar answered Sep 22 '22 16:09

Barry