我想知道是否有可能有一些编译时循环.
例如,我有以下模板类:
template<class C, int T=10, int B=10>
class CountSketch
{
public:
CountSketch()
{
hashfuncs[0] = &CountSketch<C>::hash<0>;
hashfuncs[1] = &CountSketch<C>::hash<1>;
// ... for all i until i==T which is known at compile time
};
private:
template<int offset>
size_t hash(C &c)
{
return (reinterpret_cast<int>(&c)+offset)%B;
}
size_t (CountSketch::*hashfuncs[T])(C &c);
};
Run Code Online (Sandbox Code Playgroud)
我想知道我是否可以使用循环来循环初始化T哈希函数.循环的边界在编译时是已知的,因此,原则上,我没有看到任何无法完成的原因(特别是因为它可以在我手动展开循环时起作用).
当然,在这个具体的例子中,我可以用2个参数创建一个哈希函数(虽然我猜它的效率会低一些).因此,我对解决这个特定问题不感兴趣,而是知道类似情况下是否存在"编译时间循环".
谢谢!
我曾经没有任何问题地使用math.h.现在,我使用一个外部库,它本身有一个名为的文件math.h,但包括< cmath>.
将此库添加到我的项目中(甚至只是添加include目录,而不触及代码)现在会产生大量错误< cmath>:
C:\ Program Files\Microsoft Visual Studio 8\VC\include\cmath(18):错误C2039:'acosf':不是'`global namespace''的成员
C:\ Program Files\Microsoft Visual Studio 8\VC\include\cmath(18):错误C2873:'acosf':符号不能在using声明中使用
C:\ Program Files\Microsoft Visual Studio 8\VC\include\cmath(18):错误C2039:'asinf':不是'`global namespace''的成员
C:\ Program Files\Microsoft Visual Studio 8\VC\include\cmath(18):错误C2873:'asinf':符号不能在using声明中使用
[等等...]
我不明白为什么会这样.我正在使用Visual Studio 2005并在互联网上查看,似乎这个问题在VS 2008下得到了解决.但是,我想留在VS 2005 ...
包括using namespace std;无处不在,或改变我的包含顺序似乎没有任何改变.定义_STD_BEGIN解决了错误,但产生了多少< xlocinfo>.
怎么解决这个问题?
我正准备进行编码面试,并且在图表上让我耳目一新.我想知道以下内容:在我看过的所有地方,假设邻接列表比大型稀疏图的邻接矩阵更有内存效率,因此在这种情况下应该是首选.此外,计算来自节点的输出边缘的数量需要矩阵中的O(N),而列表中的O(1),以及列表中的O(num相邻节点)中的相邻节点而不是O(N)表示矩阵.
这些地方包括Cormen等人的书,或StackOverFlow:使用邻接列表与邻接矩阵的图的大小?或维基百科.
但是,使用与压缩行存储表示相似的稀疏矩阵表示,内存要求仅为O(非零数)= O(边数),这与使用列表相同.来自节点的输出边缘的数量是O(1)(它直接存储在CRS中),并且相邻节点可以列在O(num相邻节点)中.
为什么不讨论它?我是否应该假设CSR 是由矩阵表示的图形的一种邻接列表表示?或者是矩阵存储器密集缺陷的论点,因为它们不考虑稀疏矩阵表示?
谢谢!
[编辑:感谢MSalters的回答和Raymond Chen对InterlockedIncrement与EnterCriticalSection/counter ++/LeaveCriticalSection的回答,问题解决了,下面的代码工作正常.这应该提供一个有趣的简单示例,在Windows中使用线程池]
我无法找到以下任务的简单示例.例如,我的程序需要将一个巨大的std :: vector中的值递增一,所以我想并行执行.它需要在程序的整个生命周期中多次执行此操作.我知道如何在每次调用例程时使用CreateThread,但我没有设法使用ThreadPool去掉CreateThread.
这是我做的:
class Thread {
public:
Thread(){}
virtual void run() = 0 ; // I can inherit an "IncrementVectorThread"
};
class IncrementVectorThread: public Thread {
public:
IncrementVectorThread(int threadID, int nbThreads, std::vector<int> &vec) : id(threadID), nb(nbThreads), myvec(vec) { };
virtual void run() {
for (int i=(myvec.size()*id)/nb; i<(myvec.size()*(id+1))/nb; i++)
myvec[i]++; //and let's assume myvec is properly sized
}
int id, nb;
std::vector<int> &myvec;
};
class ThreadGroup : public std::vector<Thread*> {
public:
ThreadGroup() {
pool = …Run Code Online (Sandbox Code Playgroud) 我目前有以下非模板化代码:
class Vector{
public:
double data[3];
};
static Vector *myVariable;
void func() {
myVariable->data[0] = 0.;
}
int main() {
myVariable = new Vector();
func();
}
Run Code Online (Sandbox Code Playgroud)
然后我想模拟维度:
template<int DIM> class Vector{
public:
double data[DIM];
};
static Vector<3>* myVariable;
void func() {
myVariable->data[0] = 0.;
}
int main() {
myVariable = new Vector<3>();
func();
}
Run Code Online (Sandbox Code Playgroud)
但我终于想要模拟我的变量,维度:
template<int DIM> class Vector{
public:
double data[DIM];
};
template<int DIM> static Vector<DIM> *myVariable;
void func() {
myVariable->data[0] = 0.;
// or perform any other operation …Run Code Online (Sandbox Code Playgroud) 我有一些多线程代码(请参阅问题Windows API线程池简单示例),我正在使用计数器来识别线程.
我被建议使用InterlockedIncrement在线程的回调函数中递增此计数器.然而,这似乎没有正确锁定变量,因为我遇到了一些并发问题.我通过手动使用临界区替换了InterlockedIncrement:EnterCriticalSection/counter ++/LeaveCriticalSection,现在可以完美地运行.
为什么会这样?这两个选项不应该严格等同吗?请注意,我正在谈论启动一对(大约10个)线程.
我正在建立一个具有多个(软)约束的稀疏线性系统.我正在将一些用于构建带有boost :: ublas矩阵的代码转换为Eigen.boost:ublas有一种方便的方法来创建一个具有已知(或估计)数量的非零的稀疏矩阵,并且具有相当快的运算符(int row,int col)来更新其元素.
问题如下:
使用SparseMatrix :: setFromTriplets:
我的系统有很多约束.作为一个天真的,"略微"夸大的例子,假设我有一个100x100的稀疏矩阵,500 nnz但是10亿个冗余约束(即,非零系数被修改了十亿次).setFromTriplets要求我存储10亿个系数,其中大部分将被求和以形成我的500个非零系数.这不是真正有效,也不是内存友好.当然,我可以用std :: map替换我的std :: vector,并手动执行约束的累积,但是这种方式错过了具有稀疏矩阵类的观点,而且这也没有效率.
使用SparseMatrix :: insert(i,j,val):
如果元素已经存在则不起作用.我的问题是能够累积已经存在的系数.
使用SparseMatrix :: coeffRef(i,j):
这确实有效,并且将是我正在寻找的功能.然而它比boost :: ublas慢几个数量级.我很惊讶我没有看到更好的功能.我认为这是由于事先不知道的非零数量,并强制多次重新分配(这是实践中发生的事情).但是,使用SparseMatrix :: reserve()没有任何效果,因为它是一个仅适用于压缩矩阵的函数(源代码中的注释表示"此函数在非压缩模式下没有意义",在断言之前). ..并且,正如文档所说"将新元素插入SparseMatrix后,将其转换为未压缩模式".
在Eigen中构建稀疏矩阵同时仍能多次更新其系数的最有效方法是什么?
谢谢
[编辑:示例用例:10x10矩阵,10个非零.为简单起见,矩阵是对角的]
SparseMatrix<double> mat(10, 10);
for (int i=0; i<10; i++) {
for (int j=0; j<1000000; j++) {
mat.coeffRef(i, i) += rand()%10;
}
}
Run Code Online (Sandbox Code Playgroud)
=>工作,但比ublas运算符()慢几个数量级(对于更大的矩阵和当然更真实的设置).
std::vector<Eigen::Triplet<double> > triplets(10000000);
int k=0;
for (int i=0; i<10; i++) {
for (int j=0; j<1000000; j++) {
triplets[k++] = Eigen::Triplet<double>(i,i,rand()%10);
}
}
SparseMatrix<double> mat(10, 10);
mat.setFromTriplets(triplets.begin(), triplets.end()); …Run Code Online (Sandbox Code Playgroud) 试图使用std::vector<bool>我有一个编译器错误,这对我来说非常令人惊讶.
简而言之,取一个元素的地址std::vector<unsigned char>并将其赋值给unsigned char指针:
std::vector<unsigned char> test(10);
unsigned char *pb = &test[0];
Run Code Online (Sandbox Code Playgroud)
效果非常好,同时尝试std::vector<bool>使用编译器错误导致同样的事情:
int main() {
std::vector<bool> test(10);
bool *pb = &test[0]; // line 4, compile error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在Visual Studio上,它表示如下:
std::vector bool cannot convert std::_Vb_reference<_Alloc> * to bool *
Run Code Online (Sandbox Code Playgroud)
而codepad(参见http://codepad.org/vaiN3iEq上的例子)说:
cc1plus: warnings being treated as errors
In function 'int main()':
Line 4: warning: taking address of temporary
Line 4: error: cannot convert '__gnu_norm::_Bit_reference*' to 'bool*' in initialization
compilation …Run Code Online (Sandbox Code Playgroud) 我生成了许多随机数,在C ++中需要在1到15(包括)之间。当然,我可以生成的zillons,
std::uniform_int_distribution<std::mt19937::result_type> random(1, 15);
但这是浪费的,因为此mersenn扭曲器生成32位(或使用mt19937_64甚至生成64位)随机值,而我只保留4位并丢弃所有其余值,就我而言,性能是一个问题,随机数的产生是重要的因素。
因此,我的想法是生成例如0到2 ^ 64-1之间的单个64位随机值,并从中选择4位。问题是我找不到在1到15之间生成值的方法。示例:
unsigned long long int r = uniform(generator); // between 0 and 2^64-1
unsigned int r1 = (r+1)&15; // first desired random value
unsigned int r2 = ((r>>4)+1)&15; //second desired random value
unsigned int r3 = ((r>>8)+1)&15; //third desired random value
...
Run Code Online (Sandbox Code Playgroud)
在这里,这个版本当然不起作用:尽管为+1,但生成的值仍在0到15之间(因为如果r&15碰巧0xb1111加上1会产生结果0xb0000)。
另外,我希望分布保持一致(例如,我不希望偏向最低有效位的出现频率更高,(r&15+1)|((r&15 +1) >> 4)因为值0xb0001会经常出现两次,所以可能是这种情况。
我有一个VectorN类,一个Vector3继承自的类VectorN(例如可以处理交叉产品).我无法确定不同运营商的退货类型.例:
class VectorN
{
public:
VectorN(){};
virtual VectorN operator*(const double& d) {.....};
std::vector<double> coords;
};
class Vector3 : public VectorN
{
public:
Vector3(){};
virtual Vector3 operator*(const double& d) {....};
};
Run Code Online (Sandbox Code Playgroud)
此特定示例产生C2555错误:
'vector3 :: operator*':覆盖虚函数返回类型不同,并且不是'VectorN :: operator*'的协变,请参见'VectorN :: operator*'的声明.
问题是我没有返回对a的引用Vector3,并且Vector3该类未在声明中完全定义operator*.但是,我希望我operator*是虚拟的,并且Vector3当我将a乘以Vector3常量时我想返回一个(否则,如果我这样做(Vector3*double).crossProduct(Vector3),它将返回错误).
我能做什么 ?
谢谢!
我花了几个小时,当我意识到只有我的代码的模板化版本有错误时才完全陷入困境.
在下面的代码,当在pushing_back元素myMap,原始向量myVec1和myVec2被修饰并包含垃圾在执行结束.如果我取消所有内容的模板,只需用template<T>double 替换,那么代码就可以正常工作(原始数组不受影响).
有趣的是,如果我放入一个cout,copy constructor如果代码是模板化的,它就不会被调用.但如果我用Vector<T2>原始类型替换复制构造函数,它会被调用Vector<T>,然后一切正常.
为什么编译器不会知道,T2==T因为我只使用double?
(注意,代码已尽可能短,以显示错误 - 因此我删除了访问者,使所有内容公开等).
#include <vector>
#include <map>
template<class T>
class Vector{
public:
Vector():n(0),data(0){};
Vector(int N):n(N),data(new T[N]){};
Vector(T x, T y):n(2),data(new T[2]){data[0]=x; data[1]=y;};
template<class T2> Vector(const Vector<T2>& rhs):n(rhs.n), data(new T[n])
{
for (int i=0; i<n; i++)
data[i] = T(rhs.data[i]);
}
~Vector(){delete[] data;}
Vector& operator=(const Vector& rhs)
{
if (rhs.n != n)
{
if (data)
delete[] …Run Code Online (Sandbox Code Playgroud) 在下面的代码中,我得到一个编译错误,如果我删除模板,我没有:
template<int DIM> class myClass
{
public :
enum Mode {aa,bb};
myClass(){};
};
template<int DIM> class myClass2
{
myClass2(){};
void myfunc(myClass::Mode m);
};
template<int DIM>
void myClass2<DIM>::myfunc(myClass<DIM>::Mode m)
{
}
Run Code Online (Sandbox Code Playgroud)
test.cpp(19):警告C4346:'myClass :: Mode':依赖名称不是
带有'typename' 的类型前缀,表示类型
test.cpp(19):错误C2146:语法错误:缺少')'之前标识符'm'
如果我删除之类:
template<int DIM>
void myClass2<DIM>::myfunc(myClass::Mode m)
Run Code Online (Sandbox Code Playgroud)
我明白了:
test.cpp(19):错误C2955:'myClass':使用类模板需要模板参数列表
如果我把定义myfunc直接放在类的声明中(我想避免),它就可以了.
我该怎么办?为什么会这样?
谢谢
我正在使用一个模板化的库,我不想修改它。即CImg。该库主要设计用于处理简单类型的模板:float、double、int 等。
在某些时候,这个库会:
CImg<T>& fill(const T val) {
if (is_empty()) return *this;
if (val && sizeof(T)!=1) cimg_for(*this,ptrd,T) *ptrd = val;
else std::memset(_data,(int)val,size()*sizeof(T));
return *this;
}
Run Code Online (Sandbox Code Playgroud)
现在我想使用这个库和一个更复杂的类作为模板参数。我的特定类是这样的,sizeof(T)!=1并且在大多数情况下,该fill函数会根据我的类的属性正确地分配val给每个元素operator=。但是, when !val,我想要一个转换运算符,它允许我的类被强制转换为 anint并产生一些值(例如,0会使上面的函数工作)。
现在,我的程序没有编译,因为它说:
error C2440: 'type cast' : cannot convert from 'const MyClass' to 'int'
Run Code Online (Sandbox Code Playgroud)
如何在不修改上述函数的情况下创建一个允许(int)my_variablewithmy_variable类型MyClass合法的运算符?