我遇到了nontype(int variable)模板参数的问题 为什么我不能将常量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
}
不好:编译器说,错误:'j'不能出现在常量表达式
中这就是我最终的结果。 也许有人可能会使用它,有人可能会提出更好的方法。
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);
}
答案 0 :(得分:10)
因为非类型模板参数在编译时需要值。请记住,模板是一种编译时机制;最终的可执行文件中不存在模板。还要记住,函数和函数的参数传递是运行时机制。在程序实际运行并调用j
函数之前,run()
中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);
这就是为什么编译器抱怨说''j'不能出现在常量表达式中。“
另一方面,这很好,因为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;
您可以将编译时值传递给运行时构造,但不能反过来。
但是,您可以让run()
函数接受非类型模板参数,方法与MyTemplate
模板类接受非类型模板参数的方式相同:
template<int j>
void run()
{
MyTemplate<j> b;
}
const int i = 3;
run<i>();
答案 1 :(得分:2)
基本上,C ++有两种常量:
const int a = 5;
MyTemplate<a> foo; // OK
const int b = rand();
MyTemplate<b> foo; // Not OK.
第一个例子是编译时常量。在C ++标准中,它是一个积分常数表达式(ICE)。第二个例子是运行时常量。它具有相同的C ++类型(const int
),但它不是ICE。
您的函数void run(const int j)
是运行时常量。你甚至可以传入用户输入。因此,它不是有效的模板参数。
规则的原因是编译器必须基于模板参数值生成代码。如果它没有编译时常量,则不能这样做。
答案 2 :(得分:1)
因为j应该在编译时知道。在你的例子中,它不是。