有关类模板的两个问题

时间:2021-01-05 06:17:12
1 类模板的非类型参数为一个指针时,为什么不能用常量指针作为实参?

template<int *addr>
class B{
      public:
             
             B():_addr(addr){}
      private:
              int *_addr;
};

int a=100;
int * const p=&a;

int main()
{
    A<p> aa;//编译错误 
    return 0;
}

p不是一个常量表达式吗?为什么编译不过?


2 float ,double类型能否作为类模板的非类型参数 的类型

template<double size>
class A{
      public:
             
             A():value(size){}
      private:
              double value;
};

dev C++下编译错误,VC 6下可正常编译,究竟标准C++规定float ,double类型能否作为类模板的非类型参数 的类型?

21 个解决方案

#1


这些问题,你最好看《Modern C++ Design》。
我是懒得翻了抄给你了。

#2


现在我手里找不到这本书,请哪位高手讲解一下。
多谢

#3


也没啥好讲的,编译不通过的就别用。
只要有任何一个常见编译器会不通过的,就最好别用

#4


定义为const的咚咚不能作为非const参数传给函数,不关模板的事吧?

#5


2是好像不能啊

#6


int a=100;
int * const p=&a;

int main()
{
    A<p> aa;//编译错误 
    return 0;
}
---------------------------------------------------------------------------
楼主可以改成
A<&a> aa;
现在就可以了,而且达到了相同的效果。

#7


针对楼主的第二个问题,我截取c++ standard03 14.3.2:
A template-argument for a non-type, non-template template-parameter shall be one of:
— an integral constant-expression of integral or enumeration type; or
— the name of a non-type template-parameter; or
— the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference;
or
— a pointer to member expressed as described in 5.3.1 .

注意这里说的是“integral constant-expression”,即整数系列类型的,包括char ,short, int等等。

#8


template<class T>
class B{
      public:
             
             B(T addr):_addr(addr) {};
      private:
              T _addr;
};

int a=100;
int * const p=&a;

int main()
{
    B<int*> aa(p);
    return 0;
}

大哥,你写得我看得头晕

#9


第二个问题解决了。

第一个
&a不就是一个int * const 指针吗?

p的值也能在编译期就决定,为什么不能用来作为A的实参?

#10


A<p> aa;

A 没有定义
&a 如果 a 是一个类, operator&又被重载了呢

#11


一个表达式不能做为一个非类型模板参数。

假设有模板
template<int add>
class B
{
//
};
那么:
int a=100;
int* p=&a;
int main()
{
    B<a> a1;//编译错误 
    B<10> a2;//正确
    B<*p> a2;//编译错误 
    return 0;
}

由此可以看出,OOPhaisky(异化$渴望成功~~) 是对的。

#12


楼上的表达式不是常量。
template<int add>
class B
{
//
};

const int a=100;
int* p=&a;
int main()
{
B<a> a1;//正确
B<10> a2;//正确

return 0;
}

但是const 指针就不行。

#13


第一个问题:因为p是常量指针
第二个问题:可以的,模板实参的类型和非类型模板参数的类型之间可以有一些限制的转换。一、左值转换
二、限定修饰转换
三、提升
四、整值转换

#14


我就是问为什么常量int可以而常量指针不行。

#15


C++标准规定,绑定给类模板的非类型模板参数的模板实参必须是一个常量表达式,这样明白了吧

#16


const 指针不是常量表达式吗?
和const int 一样可以在编译期就确定值。

#17


#18


d

#19


真的没有人知道什么原因?

#20


摘自<<C++ Templates>>:

Nontype template arguments are the values substituted for nontype parameters. Such a value must be one of the following things:

- Another nontype template parameter that has the right type

- A compile-time constant value of integer (or enumeration) type. This is acceptable only if the corresponding parameter has a type that matches that of the value, or a type to which the value can be implicitly converted (for example, a char can be provided for an int parameter).

- The name of an external variable or function preceded by the built-in unary & ("address of") operator. For functions and array variables, & can be left out. Such template arguments match nontype parameters of a pointer type.

- The previous kind of argument but without a leading & operator is a valid argument for a nontype parameter of reference type.

- A pointer-to-member constant; in other words, an expression of the form &C::m where C is a class type and m is a nonstatic member(data or function). This matches nontype parameters of pointer-to-member type only.

-------------------------

可以看到前面提到有关整数作为模板参数(第二点)时,可以使用编译器的常量值。像
const int size = 100;
那么int常量size可以作为模板参数。这没有问题。

但在第三点提到指针时,只说了仅能使用以内建的&运算符对具有外部连接的变量或函数取址作为
模板参数(如果变量是数组或函数,则&可省略),并没有像说整型参数时那样提到形如
int * const p = &a;
这样定义的模板常量就可以。这是语言规定,至于为何,可能有一些不是太明显的原因,我们就
不必深究过细了。

#21


常量指针跟常量表达式是两个概念。一个变量加了const并不代表它能够在编译期确定:
const int i = f();
i能够在编译期确定吗?
同理一个const指针并不代表就是能够在编译期确定的。

#1


这些问题,你最好看《Modern C++ Design》。
我是懒得翻了抄给你了。

#2


现在我手里找不到这本书,请哪位高手讲解一下。
多谢

#3


也没啥好讲的,编译不通过的就别用。
只要有任何一个常见编译器会不通过的,就最好别用

#4


定义为const的咚咚不能作为非const参数传给函数,不关模板的事吧?

#5


2是好像不能啊

#6


int a=100;
int * const p=&a;

int main()
{
    A<p> aa;//编译错误 
    return 0;
}
---------------------------------------------------------------------------
楼主可以改成
A<&a> aa;
现在就可以了,而且达到了相同的效果。

#7


针对楼主的第二个问题,我截取c++ standard03 14.3.2:
A template-argument for a non-type, non-template template-parameter shall be one of:
— an integral constant-expression of integral or enumeration type; or
— the name of a non-type template-parameter; or
— the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference;
or
— a pointer to member expressed as described in 5.3.1 .

注意这里说的是“integral constant-expression”,即整数系列类型的,包括char ,short, int等等。

#8


template<class T>
class B{
      public:
             
             B(T addr):_addr(addr) {};
      private:
              T _addr;
};

int a=100;
int * const p=&a;

int main()
{
    B<int*> aa(p);
    return 0;
}

大哥,你写得我看得头晕

#9


第二个问题解决了。

第一个
&a不就是一个int * const 指针吗?

p的值也能在编译期就决定,为什么不能用来作为A的实参?

#10


A<p> aa;

A 没有定义
&a 如果 a 是一个类, operator&又被重载了呢

#11


一个表达式不能做为一个非类型模板参数。

假设有模板
template<int add>
class B
{
//
};
那么:
int a=100;
int* p=&a;
int main()
{
    B<a> a1;//编译错误 
    B<10> a2;//正确
    B<*p> a2;//编译错误 
    return 0;
}

由此可以看出,OOPhaisky(异化$渴望成功~~) 是对的。

#12


楼上的表达式不是常量。
template<int add>
class B
{
//
};

const int a=100;
int* p=&a;
int main()
{
B<a> a1;//正确
B<10> a2;//正确

return 0;
}

但是const 指针就不行。

#13


第一个问题:因为p是常量指针
第二个问题:可以的,模板实参的类型和非类型模板参数的类型之间可以有一些限制的转换。一、左值转换
二、限定修饰转换
三、提升
四、整值转换

#14


我就是问为什么常量int可以而常量指针不行。

#15


C++标准规定,绑定给类模板的非类型模板参数的模板实参必须是一个常量表达式,这样明白了吧

#16


const 指针不是常量表达式吗?
和const int 一样可以在编译期就确定值。

#17


#18


d

#19


真的没有人知道什么原因?

#20


摘自<<C++ Templates>>:

Nontype template arguments are the values substituted for nontype parameters. Such a value must be one of the following things:

- Another nontype template parameter that has the right type

- A compile-time constant value of integer (or enumeration) type. This is acceptable only if the corresponding parameter has a type that matches that of the value, or a type to which the value can be implicitly converted (for example, a char can be provided for an int parameter).

- The name of an external variable or function preceded by the built-in unary & ("address of") operator. For functions and array variables, & can be left out. Such template arguments match nontype parameters of a pointer type.

- The previous kind of argument but without a leading & operator is a valid argument for a nontype parameter of reference type.

- A pointer-to-member constant; in other words, an expression of the form &C::m where C is a class type and m is a nonstatic member(data or function). This matches nontype parameters of pointer-to-member type only.

-------------------------

可以看到前面提到有关整数作为模板参数(第二点)时,可以使用编译器的常量值。像
const int size = 100;
那么int常量size可以作为模板参数。这没有问题。

但在第三点提到指针时,只说了仅能使用以内建的&运算符对具有外部连接的变量或函数取址作为
模板参数(如果变量是数组或函数,则&可省略),并没有像说整型参数时那样提到形如
int * const p = &a;
这样定义的模板常量就可以。这是语言规定,至于为何,可能有一些不是太明显的原因,我们就
不必深究过细了。

#21


常量指针跟常量表达式是两个概念。一个变量加了const并不代表它能够在编译期确定:
const int i = f();
i能够在编译期确定吗?
同理一个const指针并不代表就是能够在编译期确定的。