小编Ose*_*Ose的帖子

为什么64位GCC警告在分配数组时将const int转换为long unsigned int?

我有一个文件test.cpp,如下所示:

void f(const int n) {
  unsigned char *a=new unsigned char[n];
  delete[] a;
}

int main() {
  f(4);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用该-Wsign-conversion标志在64位GCC中进行编译会产生警告:

test.cpp:2:39: warning: conversion to ‘long unsigned int’ from ‘const int’ may change the sign of the result [-Wsign-conversion]
Run Code Online (Sandbox Code Playgroud)

(第2行new是调用的行).对我来说,GCC应该给出关于分配数组的警告似乎很奇怪,但以下事情甚至更奇怪:

  1. 更换违规行unsigned char *a=new unsigned char[(long unsigned int)n];并没有消除警告,也没有使用static_cast<long unsigned int>().
  2. 如果产生任何警告f与签名定义void f(T n),这里T

    1. 任何大小的任何非常量,有符号或无符号整数类型,或
    2. 带符号的64位整数类型.

    但是,当T任何const符号整数类型小于64位时,它会产生警告.

请记住,我在64位(Linux)机器上,为什么符号转换警告关心n这种情况下的常量和大小,为什么不进行类型转换可以解决问题呢?

注1:我想在另一个编译器下测试它,但是Comeau站点已关闭,我无法访问任何其他编译器,因此我无法判断这是符合标准的行为还是GCC错误.

注2:test.cpp是我所拥有的"真正的"C++文件中的一个问题的最小例子,其中我摆脱警告的最好方法是用以下方法包围违规行:

#pragma GCC diagnostic …
Run Code Online (Sandbox Code Playgroud)

c++ arrays 64-bit gcc

8
推荐指数
1
解决办法
2361
查看次数

具有指针参数的函数模板重载决策

下面的代码演示了我用来确定某个类型是否T是特定类模板的实例化的C++模板元编程模式的核心:

#include <iostream>

template<class A, class B>
struct S{};

template<class A, class B>
constexpr bool isS(const S<A,B>*) {return true;}

template<class T>
constexpr bool isS(const T*) {return false;}

int main() {
  S<int,char> s;
  std::cout<<isS(&s)<<std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

它具有两个constexpr功能模板的重载,并按预期isS输出1.如果我从第二个删除指针isS,即替换它

template<class T>
constexpr bool isS(const T) {return false;}
Run Code Online (Sandbox Code Playgroud)

该程序意外输出0.如果两个版本isS都通过编译的重载决策阶段,那么输出意味着编译器正在选择第二个重载.我已经在海湾合作委员会,并锵VC++使用在线编译器测试了这里,他们都产生相同的结果.为什么会这样?

我已多次阅读Herb Sutter的"为什么不专攻功能模板"一文,似乎这两个isS功能都应该被认为是基本模板.如果是这样,那么问题是哪一个是最专业的.通过直觉和这个答案,我希望第一个isS是最专业的,因为T可以匹配每个实例化S<A,B>*,并且有许多可能的实例化T无法匹配S<A,B>*.我想在工作草案中找到定义此行为的段落,但我不完全确定编译的哪个阶段会导致问题.是否与 …

c++ pointers function-templates overload-resolution argument-deduction

5
推荐指数
1
解决办法
567
查看次数

有没有有效的方法来超过GL_MAX_VIEWPORTS?

我目前正在实施Oikonomidis等人(2011年)提出的姿势估计算法,该算法涉及在N不同的假设姿势中渲染网格(N可能约为64个)。2.5节建议通过使用实例化同时生成多个渲染(此后它们将每个渲染减少到GPU上的单个数量)来加快计算速度,从它们的描述中,听起来好像他们找到了一种N同时生成渲染的方法。

在实现的设置阶段,我使用OpenGL视口数组定义GL_MAX_VIEWPORTS视口。然后在渲染阶段,我将GL_MAX_VIEWPORTS模型姿势矩阵的mat4 uniform数组转移到GPU内存中的数组(我仅对估计位置和方向感兴趣),并gl_InvocationID在几何着色器中使用它为每个多边形选择合适的姿势矩阵和视口的网格。

GL_MAX_VIEWPORTS我的机器上是16(我有GeForce GTX Titan),因此这种方法将允许我一次在GPU上渲染多达16个假设。事实证明这足够快,但是我对以下内容感到好奇:

有没有一种GL_MAX_VIEWPORTS限制的解决方法,该方法可能比调用渲染函数的ceil(double(N)/GL_MX_VIEWPORTS)时间更快?

我只是在几周前才开始学习基于着色器的OpenGL方法,所以我还不了解所有技巧。我最初想到的是将组合使用的内置视口支持替换为:

  1. 几何着色器,在透视投影后添加h*gl_InvocationIDy顶点的坐标(此处h是所需的视口高度),然后传递gl_InvocationID到片段着色器;和
  2. 一个片段着色器,discard片段的y坐标满足y<gl_InvocationID*h || y>=(gl_InvocationID+1)*h

但是由于担心分支discard会严重损害性能,因此我推迟了进一步研究此想法的时间。

上面论文的作者发布了一份技术报告,描述了他们的一些GPU加速方法,但还不够详细,无法回答我的问题。第3.2.3节说:“在几何实例化期间,视口信息将附加到每个顶点...一个自定义像素着色器将剪切其预定义视口之外的像素”。这听起来与我上面描述的解决方法类似,但是他们使用的是Direct3D,因此将他们在2011年能够实现的功能与今天在OpenGL中可以实现的功能进行比较并不容易。

我意识到,对我的问题的唯一确定答案是实施变通办法并衡量其性能,但是目前这是一种低优先级的好奇心,我在其他任何地方都找不到答案,因此我希望有经验的GLSL用户可以能够提供节省时间的智慧。

opengl graphics shader glsl viewport

4
推荐指数
1
解决办法
74
查看次数

在依赖范围内调用静态函数模板

假设我template<int I> void ft()在结构模板中有一个静态函数模板template<bool B> S,我想ft从另一个函数模板调用template<bool B> void g(),将bool模板参数传递gS:

template<bool B>
struct S {
  static void f() {
  }
  template<int I>
  static void ft() {
  }
};

template<bool B>
void g() {
  S<B>::f();
  S<B>::ft<12>();
}

int main() {
  g<true>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

在GCC 4.5.2中进行编译会给出关于该行的两个错误S<B>::ft<12>():

  1. 在')'令牌之前预期的主要表达
  2. 类型'<unresolved overloaded function type>'和'int'到二进制'operator <'的无效操作数

Comeau(http://www.comeaucomputing.com/tryitout/),在严格的C++ 03模式下,也抱怨该行,说明"预期的表达式",在右括号下面有一个插入符号.S<B>::f()然而,编译器都没有抱怨该行,而且Comeau实际上可以在轻松模式下编译整个最小示例.

如果我删除了g模板,而是像这样实例化S模板参数g:

void …
Run Code Online (Sandbox Code Playgroud)

c++ generic-programming function-templates class-template

3
推荐指数
1
解决办法
1604
查看次数

64位G ++ 4.6.3不会将long视为专用函数模板中的long,即使它们的大小相同.这是一个错误吗?

请考虑以下代码:

#include <iostream>
#include <cinttypes>  

template<class T>
void f();

template<>
inline void f<long long>() {
  std::cout<<"f<long long>()"<<std::endl;
}

int main(int , char** ) {
  std::cout<<"sizeof(long)="<<sizeof(long)<<std::endl;
  std::cout<<"sizeof(long long)="<<sizeof(long long)<<std::endl;
  f<int64_t>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

32位G ++ 4.6.3成功编译并生成输出:

sizeof(long)=4
sizeof(long long)=8
f<long long>()
Run Code Online (Sandbox Code Playgroud)

但是,在64位G ++ 4.6.3下进行编译会产生链接器错误:

undefined reference to `void f<long>()'
ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

即使编译并运行f<int64_t>()注释掉的行产生:

sizeof(long)=8
sizeof(long long)=8
Run Code Online (Sandbox Code Playgroud)

有没有一个很好的理由为什么64位G ++对待f<long>f<long long>作为不同的功能,即使long并且long long大小相同,或者这是一个我应该报告的错误?

c++ g++ template-specialization function-templates long-long

1
推荐指数
1
解决办法
925
查看次数

SFINAE在类模板中使用typedef失败,引用另一个类模板中的typedef

我一直在研究一种产生关于在C++中包装其他类的类的编译时信息的方法.在我要问的问题的最小例子中,这样一个包装类:

  • 包含typedef WrappedType定义包装类的类型; 和
  • 重载一个被调用的结构模板IsWrapper,表明它是一个包装类.

有一个结构模板被调用WrapperTraits,然后可用于确定包装类型层次结构的(非包装)根类型.例如,如果包装类是一个被调用的类模板Wrapper<T>,那么根类型Wrapper<Wrapper<int>>就是int.

在下面的代码片段中,我实现了一个名为a的递归结构模板GetRootType<T>,它定义了一个typedef RootType包装类型的根类型T.WrapperTraitsjust 的给定定义包含定义的根类型GetRootType,但实际上它会有一些额外的成员.为了测试它,我编写了一个普通函数f,它接受一个int重载的函数模板f,该函数模板采用任意包装类int作为其根类型.我使用SFINAE来区分它们,通过std::enable_if在函数模板的返回类型中使用来检查f参数的根类型是否为int(如果f参数不是包装器,则尝试确定其根类型将失败).在我提出问题之前,这里是代码片段:

#include <iostream>
#include <type_traits>


// Wrapper #######################################

template<class T>
struct Wrapper {typedef T WrappedType;};

template<class T, class Enable=void>
struct IsWrapper: std::false_type {};

template<class T>
struct IsWrapper<Wrapper<T> >: std::true_type {};


// WrapperTraits #######################################

template< …
Run Code Online (Sandbox Code Playgroud)

c++ templates sfinae type-traits enable-if

1
推荐指数
2
解决办法
536
查看次数