小编Cyg*_*sX1的帖子

直接从指针转换为模板函数?

我试图获取一个指向函数模板实例的指针并将其转换为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)

但是,如果错误是通过将函数指针转换为普通指针引起的,则编译器应该在两种情况下都会抱怨.但它没有,所以我继续假设它至少对于这个编译器来说是正确的.如果我没有记错的话,标准只是说,函数指针不具有像普通指针来表示,但它并没有禁止这一点.

c++ visual-c++

5
推荐指数
2
解决办法
1494
查看次数

CUDA全局内存事务的成本

根据CUDA 5.0编程指南,如果我同时使用L1和L2缓存(在Fermi或Kepler上),则所有全局内存操作都是使用128字节内存事务完成的.但是,如果我仅使用L2,则使用32字节内存事务(第F.4.2章).

我们假设所有缓存都是空的.如果我有一个warp,每个线程以完全对齐的方式访问一个4字节字,这将导致L1 + L2情况下的1x128B事务,以及仅L2情况下的4x32B事务.是对的吗?

我的问题是 - 4个32B交易是否比单个128B交易慢?我对前费米硬件的直觉表明它会更慢,但也许在新硬件上不再是这样吗?或者我可以只看一下带宽利用率来判断我的内存访问效率?

cuda

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

如何在Makefile中使用'build'和'clean'制作'rebuild'规则?

我有一个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,其将执行cleanall 按此顺序.我没有看到如何正确实现正确的订购.


我所看到的解决方案对我来说是错误的.

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取决于bc,但是如果 …

makefile

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

如何隐藏 range-v3 的复杂范围类型?

我需要一个带有使用 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)

c++ c++14 range-v3 c++17

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

有效地将int除以intmax

我有一个整数类型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 …

c++

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

无法从 spdlog 中格式化参数

我正在尝试使用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)

c++ spdlog fmt

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

在物体破坏时留下"僵尸"旗帜

我想显式地销毁一个对象(调用它上面的析构函数及其所有字段),但是我可能会发现仍然有一些指向该对象的指针.因此,我不想释放记忆; 相反,我想留下一种标志"我是一个被摧毁的对象".

我想到了以下方法:

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僵尸对象会正确释放前一个(普通)对象消耗的整个内存吗?


虽然我很感激您对如何以不同方式进行操作的意见,我可能倾向于按照您的方式进行操作 - 我仍然希望了解上述代码带来的所有风险.

c++

3
推荐指数
2
解决办法
412
查看次数

模板模板成员的消歧模板关键字:何时完全?

关于模板消歧器的问题在这里给出:

模板消歧器

在答案中我们可以读到:

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 …

c++ templates

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

访问std :: string中的空终止字符(字符串下标超出范围)

考虑以下非常简单的文本示例:

#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是否正确?或者我错过了什么?
  • 如果问题出在VS的实现方面,我怎么能轻松解决这个问题 - 希望length()每次使用时都不用调用operator[]?例如,使用c_str()[i]会安全吗?
  • 如果问题出在VS的实施方面 - 你知道它是否在VS 2012中修复了,或者将来是否会修复pehaps?

c++ visual-c++

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

对cuda的解释有很多'\ p'

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)

cuda

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

标签 统计

c++ ×7

cuda ×2

visual-c++ ×2

c++14 ×1

c++17 ×1

fmt ×1

makefile ×1

range-v3 ×1

spdlog ×1

templates ×1