简体   繁体   English

非类型模板参数

[英]Nontype template parameter

I'm having trouble with nontype(int variable) template parameter. 我遇到了nontype(int variable)模板参数的问题。
Why can't I pass a constant int variable to a function and let the function instantiate the template? 为什么我不能将常量int变量传递给函数并让函数实例化模板?

template<int size>
class MyTemplate
{
  // do something with size
};

void run(const int j)
{
  MyTemplate<j> b; // not fine
}
void main()
{
  const int i = 3;
  MyTemplate<i> a; // fine;
  run(i); // not fine
}

not fine : compiler says, error: 'j' cannot appear in constant-expression 不好:编译器说,错误:'j'不能出现在constant-expression中

  • EDIT 编辑

This is what I ended up with. 这就是我最终的结果。 Maybe someone might use it, someone might suggest better way. 也许有人可能会使用它,有人可能会提出更好的方法。

enum PRE_SIZE
{
    PRE_SIZE_256 = 256,
    PRE_SIZE_512 = 512,  
    PRE_SIZE_1024 = 1024,
};

template<int size>
    class SizedPool : public Singleton< SizedPool<size> >
{
public:
    SizedPool()
        : mPool(size)
    {
    }
    void* Malloc()
    {
        return mPool.malloc();
    }

    void Free(void* memoryPtr)
    {
        mPool.free(memoryPtr);
    }

private:
    boost::pool<>       mPool;
};

template<int size>
    void* SizedPoolMalloc()
    {
        return SizedPool<size>::GetInstance()->Malloc();
    }

template<int size>
    void SizedPoolFree(void* memoryPtr)
    {
        SizedPool<size>::GetInstance()->Free(memoryPtr);
    }

void* SizedPoolMalloc(int size)
{
    if (size <= PRE_SIZE_256)
        return SizedPoolMalloc<PRE_SIZE_256>();
    else if (size <= PRE_SIZE_512)
        return SizedPoolMalloc<PRE_SIZE_512>();
}


void toRun(const int j)
{
    SizedPoolMalloc(j);
}
void Test17()
{
    const int i = 3;
    toRun(i);
}

Because non-type template parameters require values at compile-time. 因为非类型模板参数在编译时需要值。 Remember that templates are a compile-time mechanism; 请记住,模板是一种编译时机制; templates do not exist in the final executable. 最终的可执行文件中不存在模板。 Also remember that functions and the passing of arguments to functions are runtime mechanisms. 还要记住,函数和函数的参数传递是运行时机制。 The value of the j parameter in run() will not be known until the program actually runs and invokes the run() function, well past after the compilation stage. run() j参数的值在程序实际运行之前不会知道,并且在编译阶段之后调用run()函数。

void run(const int j)
{
    // The compiler can't know what j is until the program actually runs!
    MyTemplate<j> b;
}

const int i = 3;
run(i);

That's why the compiler complains says "'j' cannot appear in constant-expression". 这就是编译器抱怨说“'j'不能出现在常量表达式中”的原因。

On the other hand, this is fine because the value of i is known at compile-time. 另一方面,这很好,因为i的值在编译时是已知的。

const int i = 3;
// The compiler knows i has the value 3 at this point,
// so we can actually compile this.
MyTemplate<i> a;

You can pass compile-time values to run-time constructs, but not the other way around. 您可以将编译时值传递给运行时构造,但不是相反。

However, you can have your run() function accept a non-type template parameter the same way your MyTemplate template class accepts a non-type template parameter: 但是,您可以让run()函数接受非类型模板参数,方法与MyTemplate模板类接受非类型模板参数的方式相同:

template<int j>
void run()
{
    MyTemplate<j> b;
}

const int i = 3;
run<i>();

Basically, C++ has two kinds of constants: 基本上,C ++有两种常量:

const int a = 5;
MyTemplate<a> foo; // OK

const int b = rand();
MyTemplate<b> foo; // Not OK.

The first example is a compile-time constant. 第一个例子是编译时常量。 In C++ standard speak, it's an Integral Constant Expression (ICE). 在C ++标准中,它是一个积分常数表达式(ICE)。 The second example is a run-time constant. 第二个例子是运行时常量。 It has the same C++ type ( const int ) but it's not an ICE. 它具有相同的C ++类型( const int ),但它不是ICE。

Your function void run(const int j) is a run-time constant. 你的函数void run(const int j)是一个运行时常量。 You could even pass in user input. 你甚至可以传入用户输入。 Therefore it's not a valid template argument. 因此,它不是有效的模板参数。

The reason for the rule is that the compiler must generate code based on the template argument value. 规则的原因是编译器必须基于模板参数值生成代码。 It can't do so if it doesn't have a compile-time constant. 如果它没有编译时常量,则不能这样做。

Because j should be known at compile time. 因为j应该在编译时知道。 In your example it is not. 在你的例子中它不是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM