我试图获取一个指向函数模板实例的指针并将其转换为void*:
#include <stdio.h>
void plainFunction(int *param) {}
template <typename T>
void templateFunction(T *param) {}
int main() {
void *addr1=&plainFunction; //OK
void *addr2=&templateFunction<int>; //Compile error
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误(在Visual Studio 2008中)
main.cu(10) : error C2440: 'initializing' : cannot convert from 'void (__cdecl *)(T *)' to 'void *'
Context does not allow for disambiguation of overloaded function
Run Code Online (Sandbox Code Playgroud)
为什么会这样?功能templateFunction(对于具体类型T=int)不会过载.可以减去我所引用的函数的哪个实例.
如果我用以下内容替换erroneus行:
void (*foo)(int*)=&templateFunction<int>;
void *addr2=foo;
Run Code Online (Sandbox Code Playgroud)
它编译没有问题.
谢谢!
更新:
当正常指针void*被虚拟函数指针替换时void(*)(),正如James(谢谢)建议的那样,它会使错误消失:
void (*addr1)()=(void(*)())&plainFunction;
void (*addr2)()=(void(*)())(&templateFunction<int>);
Run Code Online (Sandbox Code Playgroud)
但是,如果错误是通过将函数指针转换为普通指针引起的,则编译器应该在两种情况下都会抱怨.但它没有,所以我继续假设它至少对于这个编译器来说是正确的.如果我没有记错的话,标准只是说,函数指针不具有像普通指针来表示,但它并没有禁止这一点.
根据CUDA 5.0编程指南,如果我同时使用L1和L2缓存(在Fermi或Kepler上),则所有全局内存操作都是使用128字节内存事务完成的.但是,如果我仅使用L2,则使用32字节内存事务(第F.4.2章).
我们假设所有缓存都是空的.如果我有一个warp,每个线程以完全对齐的方式访问一个4字节字,这将导致L1 + L2情况下的1x128B事务,以及仅L2情况下的4x32B事务.是对的吗?
我的问题是 - 4个32B交易是否比单个128B交易慢?我对前费米硬件的直觉表明它会更慢,但也许在新硬件上不再是这样吗?或者我可以只看一下带宽利用率来判断我的内存访问效率?
我有一个Makefile,其中包含用于构建小项目和清理它的规则.例如:
CC:=gcc
LD:=gcc
SOURCES:=$(wildcard src/*.c)
OBJS:=$(SOURCES:src/%.c=build/%.o)
TARGET:=bin/program
all: $(TARGET)
$(TARGET): $(OBJS)
@mkdir -p bin
$(LD) $+ -o $@
build/%.o: src/%.c
@mkdir -p build
$(CC) $+ -c -o $@
clean:
rm -rf $(OBJS)
rm -rf $(TARGET)
rmdir bin
rmdir build
.PHONY: clean all
Run Code Online (Sandbox Code Playgroud)
我现在在创建规则兴趣rebuild,其将执行clean并all 按此顺序.我没有看到如何正确实现正确的订购.
我所看到的解决方案对我来说是错误的.
rebuild: clean all
.PHONY: rebuild
Run Code Online (Sandbox Code Playgroud)
自然是错误的,因为无法保证依赖关系实际按其外观顺序执行.all可能之前执行clean.
我已经看到了建议仅限订单依赖的答案,例如
rebuild: | clean all
.PHONY: rebuild
Run Code Online (Sandbox Code Playgroud)
据我所知,这并没有解决问题.如果你说它a: | b c意味着a取决于b和c,但是如果 …
我需要一个带有使用 range-v3 库返回某种范围的方法的类。为了实现这样的类,我可以在该类的定义中正确地编写所有内容。例如:
#include <iostream>
#include <set>
#include <range/v3/view/transform.hpp>
class Alpha {
public:
int x;
};
class Beta : public Alpha {};
class Foo {
public:
std::set<Alpha*> s;
auto r() { return s | ranges::v3::view::transform([](Alpha* a) { return static_cast<Beta*>(a); }) }
};
Run Code Online (Sandbox Code Playgroud)
但是,在我的真实案例中,该Foo::r函数非常复杂,我想隐藏它的实现。特别是,实现使用了一些额外的库,否则在Foo声明类时不需要包含这些库。
但是,当 的定义Foo::r与其声明分开时,必须明确指定其返回类型。decltype有一些帮助:
头文件:
class Foo {
public:
std::set<Alpha*> s;
using RangeReturn = decltype(std::declval<std::set<Alpha*>&>() | ranges::v3::view::transform(std::function<Beta*(Alpha*)>()));
RangeReturn r();
};
Run Code Online (Sandbox Code Playgroud)
实现,cpp文件:
#include "Foo.h"
Foo::RangeReturn Foo::r() {
return s | ranges::v3::view::transform(std::function<Beta*(Alpha*)>{ …Run Code Online (Sandbox Code Playgroud) 我有一个整数类型uint32_t,想将其除以的最大值,uint32_t并得到a的结果float(范围为0..1)。
当然,我可以执行以下操作:
float result = static_cast<float>(static_cast<double>(value) / static_cast<double>(std::numeric_limits<uint32_t>::max()))
Run Code Online (Sandbox Code Playgroud)
但是,这实际上是很多转换,而除法本身可能会很昂贵。
Is there a way to achieve the above operation faster, without division and excess type conversions? Or maybe I shouldn't worry because modern compilers are able to generate an efficient code already?
Edit: division by MAX+1, effectively giving me a float in range [0..1) would be fine too.
A bit more context:
I use the above transformation in a time-critical loop, with uint32_t being …
我正在尝试使用spdlog. 我将其合并到我的代码中,但现在出现以下错误:
....fmt\core.h(1016): error C2338: Cannot format argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#formatting-user-defined-types
....fmt/core.h(1013): note: while compiling class template member function 'int fmt::v6::internal::arg_mapper<Context>::map(...)'
with
[
Context=context
]
....fmt/core.h(1213): note: see reference to function template instantiation 'int fmt::v6::internal::arg_mapper<Context>::map(...)' being compiled
with
[
Context=context
]
....fmt/core.h(1027): note: see reference to class template instantiation 'fmt::v6::internal::arg_mapper<Context>' being compiled
with
[
Context=context
]
....fmt/core.h(1198): note: see reference to alias template instantiation 'fmt::v6::internal::mapped_type_constant<int,context>' being compiled
....fmt/core.h(1342): note: see reference …Run Code Online (Sandbox Code Playgroud) 我想显式地销毁一个对象(调用它上面的析构函数及其所有字段),但是我可能会发现仍然有一些指向该对象的指针.因此,我不想释放记忆; 相反,我想留下一种标志"我是一个被摧毁的对象".
我想到了以下方法:
class BaseClass { //all objects in question derive from this class
public:
BaseClass() : destroyed(false) {}
virtual ~BaseClass() {}
private:
bool destroyed;
public:
bool isDestroyed() { return destroyed; }
void destroy() {
this->~BaseClass(); //this will call the virtual destructor of a derivative class
new(this) BaseClass();
destroyed=true;
}
};
Run Code Online (Sandbox Code Playgroud)
当destroy被召唤时,我基本上会破坏我拥有的任何物体(可能是衍生物)并在同一个地方创建一个新的"僵尸".因此,我希望实现:
ptr先前指向此对象的任何其他指针仍可调用ptr->isDestroyed()以验证其存在.BaseClass)delete仍然正确吗?问题:
使用上述模式时是否还有其他问题需要考虑?
调用delete僵尸对象会正确释放前一个(普通)对象消耗的整个内存吗?
虽然我很感激您对如何以不同方式进行操作的意见,我可能倾向于按照您的方式进行操作 - 我仍然希望了解上述代码带来的所有风险.
关于模板消歧器的问题在这里给出:
在答案中我们可以读到:
ISO C++ 03 14.2/4
当成员模板专业化的名称出现之后.或 - >在postfix-expression中,或在qualified-id中的nested-name-specifier之后,postfix-expression或qualified-id显式依赖于template-parameter(14.6.2),成员模板名称必须是以关键字模板为前缀.否则,假定该名称命名非模板.
现在我来到这个我不太明白的例子:
template <class T>
class Base {
public:
template <int v>
static int baseGet() {return v;}
class InnerA {
public:
template <int v>
static int aget() {return v;}
};
class InnerB {
public:
typedef Base BaseType;
typedef BaseType::InnerA OtherType;
template <int v>
static int baseGet() {return BaseType::baseGet<v>();} //(A)
template <int v>
static int aget() {return OtherType::aget<v>();} //(B)
};
};
Run Code Online (Sandbox Code Playgroud)
它显然无法编译.你需要template在(B)行:OtherType::template aget<v>();.然而,g ++(4.4.3)和clang ++(2.9)都没有抱怨template线(A)缺乏.为什么?BaseType …
考虑以下非常简单的文本示例:
#include <stdio.h>
#include <string>
int main() {
std::string x("ugabuga");
int i=0;
while (x[i]) {
++i;
}
printf("%d\n",i); //should print 7
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望程序迭代字符串的所有字符,然后到达空终止字符,打破循环并正确到达程序结束.但是,当我尝试在Visual Studio 2010下以调试模式编译它时,我到达了一个异常"字符串下标超出范围".在发布模式下编译时,这个程序会通过,但是我的大项目取决于这种行为崩溃 - 也许是因为这个问题.
但是,当我检查www.cplusplus.com的规范std::string::operator[]时,显式处理结束字符串:
如果pos等于字符串长度,则该函数返回对空字符('\ 0')的引用.
我想问一下:
std::string是否正确?或者我错过了什么?length()每次使用时都不用调用operator[]?例如,使用c_str()[i]会安全吗?extern __host__ cudaError_t CUDARTAPI cudaMemcpy(void *dst, const void *src, size_t count, enum cudaMemcpyKind kind);
/**
* \brief Copies memory between two devices
*
* Copies memory from one device to memory on another device. \p dst is the
* base device pointer of the destination memory and \p dstDevice is the
* destination device. \p src is the base device pointer of the source memory
* and \p srcDevice is the source device. \p count specifies the number of
*/ …Run Code Online (Sandbox Code Playgroud)