根据数据返回不同的数据类型(C ++)

时间:2009-05-31 00:23:53

标签: c++ return-value

无论如何都要做这样的事情?

(correct pointer datatype) returnPointer(void* ptr, int depth)
{

    if(depth == 8)
        return (uint8*)ptr;
    else if (depth == 16)
        return (uint16*)ptr;
    else
        return (uint32*)ptr;
}

由于

5 个答案:

答案 0 :(得分:10)

没有。 C ++函数的返回类型只能根据显式模板参数或其参数的 types 而变化。它不能根据其参数的而变化。

但是,您可以使用各种技术来创建一个类型,该类型是其他几种类型的并集。不幸的是,这不一定对你有帮助,因为这样的技术本身就是无效的,回到原来的类型会很痛苦。

然而,通过将问题彻底解决,你可能会得到你想要的东西。我想你会想要使用你发布的代码,例如:

void bitmap_operation(void *data, int depth, int width, int height) {
  some_magical_type p_pixels = returnPointer(data, depth);
  for (int x = 0; x < width; x++)
    for (int y = 0; y < width; y++)
      p_pixels[y*width+x] = some_operation(p_pixels[y*width+x]);
}

因为C ++需要在编译时知道p_pixels的类型,所以这不会按原样工作。但是我们能做的是让bitmap_operation本身成为一个模板,然后用一个基于深度的开关包装它:

template<typename PixelType>
void bitmap_operation_impl(void *data, int width, int height) {
  PixelType *p_pixels = (PixelType *)data;
  for (int x = 0; x < width; x++)
    for (int y = 0; y < width; y++)
      p_pixels[y*width+x] = some_operation(p_pixels[y*width+x]);
}

void bitmap_operation(void *data, int depth, int width, int height) {
  if (depth == 8)
    bitmap_operation_impl<uint8_t>(data, width, height);
  else if (depth == 16)
    bitmap_operation_impl<uint16_t>(data, width, height);
  else if (depth == 32)
    bitmap_operation_impl<uint32_t>(data, width, height);
  else assert(!"Impossible depth!");
}

现在编译器会为你自动为bitmap_operation_impl生成三个实现。

答案 1 :(得分:7)

如果可以使用模板参数而不是普通参数,则可以创建模板化函数,为每个depth值返回正确的类型。首先,需要根据depth对正确类型进行一些定义。您可以为不同的位大小定义具有特化的模板:

// template declaration
template<int depth>
struct uint_tmpl;

// specializations for certain types
template<> struct uint_tmpl<8>  { typedef uint8_t type; };
template<> struct uint_tmpl<16> { typedef uint16_t type; };
template<> struct uint_tmpl<32> { typedef uint32_t type; };

此定义可用于声明模板化函数,该函数为每个位值返回正确的类型:

// generic declaration
template<int depth>
typename uint_tmpl<depth>::type* returnPointer(void* ptr);

// specializations for different depths
template<> uint8_t*  returnPointer<8>(void* ptr)  { return (uint8_t*)ptr;  }
template<> uint16_t* returnPointer<16>(void* ptr) { return (uint16_t*)ptr; }
template<> uint32_t* returnPointer<32>(void* ptr) { return (uint32_t*)ptr; }

答案 2 :(得分:1)

您可以在堆上分配一些内存,并返回一个void *,您将其转换为已分配的类型。它是一种危险且不安全的工作方式,是一种古老的C技巧。

您可以返回包含所有有效数据类型(和选择指示符)的联合。

您可以使用模板,这是推荐的C ++方式。

您可以提供一组重载函数,这些函数将参数(每种类型)作为参考 - 编译器将根据数据类型决定调用哪个函数。我经常喜欢这种方式,因为我觉得它最简单。

答案 3 :(得分:0)

没有;你不能用C ++做到这一点。正确答案是返回void *

从调用的反面思考 - 从编译器的角度来看:

编译器如何能够验证返回值是否正确使用(例如,分配给正确类型的变量),如果它不可能知道将返回三种返回类型中的哪一种?

此时,将“多种类型之一”分配给返回值的概念变得毫无意义。函数的返回类型在生活中没有其他目的,只能使编译器完成它的工作;编译器需要“one”类型才能进行类型检查。由于在运行之前您不知道它是哪一个,因此编译器无法为您进行类型检查。您必须告诉编译器“停止尝试”将返回值与任何特定指针类型相匹配 - 因此,返回void *

如果您的深度参数在编译时已知,您可以使用一组模板,如@sth演示,或使用一组独立的独立函数,或使用一组调用共享实现的相关函数函数然后将返回转换为正确的类型。你选择哪一个主要是一个美学决定。

如果在运行时才知道depth的值,那么您应该返回void *

现在,我假设您的实际实现实际上会产生一些东西,而不是示例代码显示的指针。您的示例代码不是实际功能;这更像是试图复制cast所做的事情。 cast不是函数调用;它是一个编译器指令,试图将它的操作数“变为”特定类型(确切地说'如何',这是另一篇文章的长篇故事)。它不是C ++语言操作,而是编译器操作。你不能用C ++本身重写它。

答案 4 :(得分:0)

你可以这样做:

如果(深度== 8)     (uint8 *)returnPointer(void * ptr,int depth){// etc

相关问题