首页 > 解决方案 > 类型别名允许分配任意指针,尽管需要 int*

问题描述

我今天遇到了一个有趣的问题,涉及从不匹配类型的函数指针分配给指针。

编辑:受@Frank启发的较短示例:

void printSquare(int x) { printf("%d\n", x * x); }

int* foo() {
  using res_t = int*;

  return res_t(printSquare);
}

我希望代码不会编译,因为函数的返回类型应该是int*,它决不能从类型系统边界内的函数引用或指针创建(就我而言意识到)。直接返回或者res_tint *编译器替换的时候会拒绝这个程序,但是中间加上using-declaration,就编译运行了(当然指向的位置不包含int,而是函数)。

原始代码和问题保留在下面的单独答案中。

标签: c++c++11variadic-templatestemplate-meta-programming

解决方案


您不是在构造指针,而是在转换指针,这在 C 风格的指针转换规则下是合法的。

举个例子,以下内容等同于您正在做的事情,并且编译得很好(不幸的是,但出于兼容性原因是必要的):

float some_val = 0.0f;
int* foo() {
  using res_t = int*;

  return res_t(&some_val);
}

在我的脑海中,你可以像这样解决这个问题:

if(pos != end(container)) {
  return pos->second;
}
else {
  C val(std::forward<First>(first), std::forward<Args>(args)...);
  return val;
}

但如果没有更优雅的方式来做到这一点,我会感到惊讶。

编辑:

直接分配或返回不匹配的指针不会编译

正确,但这不是您正在做的事情,您不是在分配指针,而是在投射它。句法转换非常松散。您可能已经看过以下内容:

int * a;
float * b = (float*)a;

现在考虑数字类型之间的转换是如何工作的:

int a = 0;
short b = (int)a;
short c = int(a);

'b' 和 'c' 语句是等价的。第三个语句不是构造,它仍然是cast,并且相同的语法规则适用于指针(为了一致性)。

但是:c(function-style cast) 使用的语法不能直接访问,因为以下内容没有语法意义:

float* d = float*(&a);

但是在使用类型别名时它仍然可以工作:

using float_ptr = float*;
float* d = float_ptr(&a);

推荐阅读