Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't use pointer as a default template parameter

I am trying to use default raw pointer as a default template parameter. I read that non type template parameters are restricted to integral types, enums, pointers and references. With references I had no issues, but when I tried to use pointer I am facing such error:

error: non-type template argument of type 'Engine *' is not a constant expression.

Here is my code:

#include <iostream>
#include <memory>

using std::cout;
using std::endl;

class Engine
{
public:
    void startEngine()
    {
        m_started = true;
        cout << "Engine started!" << endl;
    }
private:
    bool m_started = false;
};

template<typename T, T* DEFAULT>
class Car
{
public:
    explicit Car(const uint64_t uid) : m_uid(uid), engine(DEFAULT)
    {
        engine->startEngine();
    }

private:
    uint64_t m_uid;
    T* engine;
};

namespace
{
    std::shared_ptr<Engine> engine = std::make_shared<Engine>();
    Engine* e = engine.get();
}

int main()
{
    Car<Engine, e> lambo(0);
    return 0;
}

The only restriction as I see now is that second template argument needs to have static storage duration and external or internal linkage but the code fits these requirements. Appreciate any help.

like image 361
Oleg Avatar asked Mar 03 '23 11:03

Oleg


2 Answers

non-type template arguments must be a constant expression:

A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter.


Perhaps you can workaround this making the object you point has static storage duration and linkage (see):

For pointers to objects, the template arguments have to designate the address of a complete object with static storage duration and a linkage (either internal or external), or a constant expression that evaluates to the appropriate null pointer or std::nullptr_t value.

Example:

namespace{
    Engine e;
}

int main(){
    Car<Engine, &e> lambo(0);
    return 0;
}
like image 175
João Paulo Avatar answered Mar 14 '23 20:03

João Paulo


As with any non-type template parameter, a pointer template parameter has to be known at compile time, or, in C++ Standard parlance, be a constant expression. And your pointer is not - compiler has no way of knowing what this address going to be when the program is executed.

like image 31
SergeyA Avatar answered Mar 14 '23 20:03

SergeyA