我发现自己最近越来越多地使用C++ 11,而且过去我会使用迭代器,我现在尽可能使用基于范围的for循环:
std::vector<int> coll(10);
std::generate(coll.begin(), coll.end(), []() { return rand(); } );
Run Code Online (Sandbox Code Playgroud)
C++ 03:
for (std::vector<int>::const_iterator it = coll.begin(); it != coll.end(); ++it) {
foo_func(*it);
}
Run Code Online (Sandbox Code Playgroud)
C++ 11:
for (auto e : coll) { foo_func(e); }
Run Code Online (Sandbox Code Playgroud)
但是,如果集合元素类型是模板参数呢?foo_func()
可能会重载以通过const引用传递复杂(=昂贵的复制)类型,并通过值传递简单的类型:
foo_func(const BigType& e) { ... };
foo_func(int e) { ... };
Run Code Online (Sandbox Code Playgroud)
当我使用上面的C++ 03风格的代码时,我没有多想.我会以相同的方式迭代,因为取消引用const_iterator会产生一个const引用,一切都很好.但是使用C++ 11基于范围的for循环,我需要使用const引用循环变量来获得相同的行为:
for (const auto& e : coll) { foo_func(e); }
Run Code Online (Sandbox Code Playgroud)
突然间我不再确定了,如果这auto
是一个简单的类型(例如实现引用的幕后指针),这将不会引入不必要的汇编指令.
但是编译示例应用程序确认了简单类型没有开销,这似乎是在模板中使用基于范围的for循环的通用方法.如果不是这种情况,那么boost :: call_traits :: param_type就是这样的.
问题:标准中是否有任何保证?
(我意识到这个问题与基于范围的for循环并不真正相关.当使用const_iterators时它也存在.)
特定
struct A {
int foo(double a, std::string& b) const;
};
Run Code Online (Sandbox Code Playgroud)
我可以像这样创建一个成员函数指针:
typedef int (A::*PFN_FOO)(double, std::string&) const;
Run Code Online (Sandbox Code Playgroud)
很容易,但PFN_FOO
如果A::foo
签名发生变化则需要更新.自C++ 11引入以来decltype
,它是否可以用于自动推导签名并创建typedef?
我正在使用VC++ 11(CTP Update 1)编译x86目标时遇到随机浮点错误.请参阅下面的简短示例"test.cpp",并使用以下命令进行编译:
cl /GL /O2 /EHsc test.cpp /link /MACHINE:X86
Run Code Online (Sandbox Code Playgroud)
输出应该是10 == 10
,但它会10 == 0
在/GL
(整个程序优化)启用时产生.问题似乎是get_scaling_factor()
将结果推送到浮点堆栈,但调用函数期望它在SSE寄存器XMM0中.
问题:我错过了一些明显的东西,还是这真的是一个错误?当然,测试程序没有意义,因为它是一个简化的测试用例.
TEST.CPP:
#include <iostream>
template <typename T>
inline T get_scaling_factor(int units)
{
switch (units)
{
case 0: return 1;
case 1: return 10;
case 2: return 100;
case 3: return 1000;
case 4: return 10000;
case 5: return 100000;
case 6: return 1000000;
case 7: return 10000000;
case 8: return 100000000; …
Run Code Online (Sandbox Code Playgroud) c++ visual-c++ compiler-bug visual-studio-2012 visual-c++-2012
我知道C++不支持容器元素的协方差,就像在Java或C#中一样.所以下面的代码可能是未定义的行为:
#include <vector>
struct A {};
struct B : A {};
std::vector<B*> test;
std::vector<A*>* foo = reinterpret_cast<std::vector<A*>*>(&test);
Run Code Online (Sandbox Code Playgroud)
毫不奇怪,我在建议这个解决另一个问题时收到了downvotes .
但是C++标准的哪一部分确切地告诉我这将导致未定义的行为?它的保证,无论std::vector<A*>
和std::vector<B*>
他们的指针存储在内存中的continguous块.它也保证了sizeof(A*) == sizeof(B*)
.最后,A* a = new B
完全合法.
那么我标准的标准是什么坏的(风格除外)?
我需要部署针对Windows 64位和32位的软件设置.我为每个平台都有两个独立的Windows Installer数据库(使用WiX创建),我使用dotNetInstaller将它们组合成一个安装的bootstrapper可执行文件.
我目前正在使用dotNetInstaller的1.10版并设置auto_close_if_installed=True
,因为我想完全隐藏用户的引导程序.尽管如此,dotNetInstaller坚持在我的安装程序运行时显示窗台进度条窗口,并且不会自动关闭.用户需要确认一个对话框,告诉他应用程序已成功安装.但真正的交易破坏者是它还不支持Windows 8.
升级到更高版本的dotNetInstaller似乎打破了auto_close_if_installed
,所以情况更糟.
所以我的问题是:在一个可执行文件中部署这两个设置的当前技术水平是什么.Wix Burn会成为一个选择吗?
我知道在理想的世界里,我只是为我的客户提供单独的安装程序.但他们碰巧完全没有意识到这些微妙之处,他们中的大多数甚至都不知道他们正在使用什么平台.
我意识到之前已经问过这个问题 - 但是没有一个答案适用于我的具体案例:
我有一个包含本机C++ EXE项目的解决方案,该项目依赖于40多个本机C++ DLL项目(在同一解决方案中).
EXE项目具有通常的调试,发布(和配置文件)配置,但由于它们使用相同的源代码库来构建三个不同的应用程序(例如A1,A2和A3).此外,它以x32和x64为目标,因此总共有3 x 3 x 2 = 18个项目配置.
DLL项目由所有三个目标应用程序共享,因此只有3个(调试,发布,配置文件)时间2(x32,x64)= 6个配置.
由于EXE项目依赖于DLL,因此无论何时修改,它都需要将DLL项目的相关输出复制到其目标文件夹(或其子文件夹).
你会如何处理DLL的更新?
每个DLL项目中的构建后操作都不起作用(因为)它必须将DLL复制到A1,A2和A3的相关输出文件夹.输出文件夹中的任何更改都会导致必须修改50个DLL项目中的每个项目中的构建后操作.
我目前将DLL本身作为项目项添加到EXE项目中,并配置了自定义构建工具以将其复制到输出文件夹.但这需要我添加每个DLL 6次,所以我最终得到6 x 50 = 300个DLL!
我真正需要的是类似于复制本地选项,不幸的是只能使用程序集.您是否建议简化此构建设置?
鉴于一个简单的template <typename T> struct X { T x, y; };
,我想提供转换构造函数,以便用户可以编写:
X<double> a;
X<int16_t> b = a; // uses implicit conversion ctr (compiles with warning)
X<int16_t> c(a); // uses explicit conversion ctr (compiles w/o warning)
X<int32_t> d = c; // uses implicit conversion ctr (compiles w/o warning)
Run Code Online (Sandbox Code Playgroud)
我相信为了实现这个目标,我需要从类型实现隐式和显式转换构造函数U
.但是不可能在"隐含"上重载explicit
:
template <typename T> struct X {
X(T x = T(), T y = T()) : x(x), y(y) {}
// implicit conversion
template <typename U>
X(const X<U>& other) …
Run Code Online (Sandbox Code Playgroud) 给出一个类声明
class A {
template <typename T> T foo();
};
Run Code Online (Sandbox Code Playgroud)
我想专门A::foo
研究各种类型(int
,...)和类型类(POD,非POD)T
.不幸的是,我似乎无法std::enable_if
用于后者.以下内容无法编译:
template <> int A::foo<int>(); // OK
template <typename T>
typename std::enable_if<is_pod<T>::value, T>::type foo(); // <<<< NOT OK!
template <typename T>
typename std::enable_if<!is_pod<T>::value, T>::type foo(); // <<<< NOT OK!
Run Code Online (Sandbox Code Playgroud)
问题可能是因为这些std::enable_if<...>
东西是函数签名的一部分,而且我没有在里面声明任何这样的成员A
.那么如何根据类型特征专门化模板成员呢?
我无法在Win32应用程序中找到挂起的原因.该软件以紧凑的循环将一些数据呈现给OpenGL视觉:
std::vector<uint8_t> indices;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_DOUBLE, 0, vertexDataBuffer);
while (...) {
// get index type (1, 2, 4) and index count
indices.resize(indexType * count);
// get indices into "indices" buffer
getIndices(indices.data(), indices.size()); //< seems to hang here!
// draw (I'm using the correct parameters)
glDrawElements(GL_TRIANGLES_*, count, GL_UNSIGNED_*);
}
glDisableClientState(GL_VERTEX_ARRAY);
Run Code Online (Sandbox Code Playgroud)
代码使用VC11 Update 1(CTP 3)编译.在运行优化的二进制文件时,它会getIndices()
在几个循环之后挂起调用(更多关于此内容).我已经有了...
我并没有找到该代码访问分配的缓冲区,也没有任何堆损坏任何问题.但是,如果我禁用低碎片堆,问题就会消失.如果我为indices
缓冲区使用单独的(低碎片)堆,它也会消失.
无论如何,这是导致死锁的堆栈跟踪:
0:000> kb
ChildEBP RetAddr Args to …
Run Code Online (Sandbox Code Playgroud) 可能重复:
C++ 0x和缺乏多态Lambda - 为什么?
C++ 0x lambda表达式支持返回类型推断到某一点.为什么参数类型也不是自动确定的?
例如,为什么我不能写:
void somefunc(const std::vector<int>& v)
{
std::sort(v.begin(), v.end(), [](x, y) { return x < y; });
}
Run Code Online (Sandbox Code Playgroud)
似乎编译器应该能够找出它x
并且y
是类型的int
.
c++ ×8
c++11 ×5
templates ×3
compiler-bug ×1
covariance ×1
debugging ×1
decltype ×1
lambda ×1
native ×1
visual-c++ ×1
windbg ×1
wix ×1