不能使用指针作为默认模板参数

时间:2019-09-05 14:06:45

标签: c++ pointers templates

我正在尝试使用默认的原始指针作为默认的模板参数。我读到非类型模板参数仅限于整数类型,枚举,指针和引用。使用引用我没有问题,但是当我尝试使用指针时,我遇到了这样的错误:

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

这是我的代码:

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

我现在看到的唯一限制是第二个模板参数需要具有静态存储持续时间以及外部或内部链接,但是代码符合这些要求。感谢任何帮助。

3 个答案:

答案 0 :(得分:5)

非类型模板参数必须为常量表达式:

  

非类型模板参数的模板参数应为   转换后的常量表达式(5.20)的类型   模板参数。


也许您可以解决此问题,使指向的对象具有静态存储持续时间和链接(see):

  

对于指向对象的指针,模板参数必须指定   具有静态存储持续时间的完整对象的地址和   链接(内部或外部),或一个常量表达式   计算为适当的空指针或std :: nullptr_t值。

示例:

namespace{
    Engine e;
}

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

答案 1 :(得分:2)

与任何非类型模板参数一样,指针模板参数在编译时必须是已知的,或者按照C ++标准的说法,应为常量表达式。而且您的指针不是-编译器无法知道程序执行时该地址将是什么。

答案 2 :(得分:0)

它不起作用,因为参数必须是常量表达式。

因此通过以下方式强制进行持续评估:

namespace
{
    Engine ee; 
}

int main()
{
    Car<Engine, &ee> lambo(0);