小编Jam*_*ree的帖子

可以使用std :: uintptr_t来避免越界指针算法的未定义行为吗?

现在我们知道,越界 - 指针算术具有未定义的行为,如本SO问题所述.

我的问题是:我们可以通过转换为std :: uintptr_t进行算术运算然后转换回指针来解决这种限制吗?是保证工作吗?

例如:

char a[5];
auto u = reinterpret_cast<std::uintptr_t>(a) - 1;
auto p = reinterpret_cast<char*>(u + 1); // OK?
Run Code Online (Sandbox Code Playgroud)

真实世界的用法是优化偏移内存访问 - 而不是p[n + offset]我想做的offset_p[n].

编辑使问题更明确:

给定一个pchar数组的基指针,如果p + n是一个有效的指针,将reinterpret_cast<char*>(reinterpret_cast<std::uintptr_t>(p) + n)保证产生相同的有效指针?

c++ pointers pointer-arithmetic

7
推荐指数
2
解决办法
1379
查看次数

在constexpr中使用argc,是否严格要求所涉及的任何子表达式都是常量表达式?

例:

int main(int argc, char**)
{
    constexpr int a = argc * 0;
    (void)a;
    constexpr int b = argc - argc;
    (void)b;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

argc不是常量表达式,但编译器仍能够在两种情况下计算结果ab编译时间(即0).

g ++接受上面的代码,而clang和MSVC14拒绝它.

标准是否允许编译器与g ++一样聪明constexpr

c++ gcc language-lawyer constexpr c++11

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

函数参数包的模板参数推导后跟其他参数

扣除f1f2形成不良?

template<class... T, class U>
void f1(T..., U){}

template<class... T>
void f2(T..., int){}

int main()
{
    f1(1);
    f2(1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

g ++接受两者,clang只接受f2,而msvc拒绝这两者.

相关标准措辞:

[temp.deduct.call]

当函数参数包出现在非推导的上下文([temp.deduct.type])中时,永远不会推导出该参数包的类型.

[temp.deduct.type] P5

未推断的上下文是:

  • 函数参数包,不会出现在参数声明列表的末尾.

所以似乎MSVC拒绝两者都是正确的?

这是否意味着即使您明确指定模板args,模板的任何实例化都将是格式错误的?

f1<int>(1, 2); // ill-formed?
f2<int>(1, 2); // ill-formed?
Run Code Online (Sandbox Code Playgroud)

如果是这样的话,为什么要在第一时间允许这样的声明呢?

c++ variadic-templates c++11 template-argument-deduction

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

Boost.Compute比普通CPU慢?

我刚开始玩Boost.Compute,看看它能为我们带来多少速度,我写了一个简单的程序:

#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/foreach.hpp>
#include <boost/compute/core.hpp>
#include <boost/compute/platform.hpp>
#include <boost/compute/algorithm.hpp>
#include <boost/compute/container/vector.hpp>
#include <boost/compute/functional/math.hpp>
#include <boost/compute/types/builtin.hpp>
#include <boost/compute/function.hpp>
#include <boost/chrono/include.hpp>

namespace compute = boost::compute;

int main()
{
    // generate random data on the host
    std::vector<float> host_vector(16000);
    std::generate(host_vector.begin(), host_vector.end(), rand);

    BOOST_FOREACH (auto const& platform, compute::system::platforms())
    {
        std::cout << "====================" << platform.name() << "====================\n";
        BOOST_FOREACH (auto const& device, platform.devices())
        {
            std::cout << "device: " << device.name() << std::endl;
            compute::context context(device);
            compute::command_queue queue(context, device);
            compute::vector<float> device_vector(host_vector.size(), context);

            // …
Run Code Online (Sandbox Code Playgroud)

c++ boost opencl boost-compute

6
推荐指数
2
解决办法
1714
查看次数

可变函数/非可变模板之间函数类型衰减的不一致性?

给定一个非可变函数模板:

template<class T>
void f(void(t)(T));
Run Code Online (Sandbox Code Playgroud)

还有一些简单的功能:

void f1(int);
void f2(char);
Run Code Online (Sandbox Code Playgroud)

这有效:

f(f1);
Run Code Online (Sandbox Code Playgroud)

类型t变成了void (*)(int).

但是,可变对应物:

template<class... T>
void f(void(...t)(T));

// call
f(f1, f2);
Run Code Online (Sandbox Code Playgroud)

不起作用.编译器(gcc&clang)抱怨不匹配的类型void(T)void (*)(int).见DEMO.

请注意,如果*明确添加,它可以正常工作:

template<class... T>
void f(void(*...t)(T));
Run Code Online (Sandbox Code Playgroud)

那么,为什么非可变参数可以衰减函数类型而可变参数不能?

c++ language-lawyer function-templates variadic-templates c++11

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

如何使用模板中的C-linkage创建函数?

在看到SO答案后,我可能有点迟到知道这个标准陈述:

[C++ 11:7.5/1]

具有不同语言链接的两种函数类型是不同的类型,即使它们在其他方面是相同的.

这意味着,给定:

void f1();
extern "C" void f2();
Run Code Online (Sandbox Code Playgroud)

decltype(f1) 是不一样的 decltype(f2)

直到现在我才意识到的一个原因是主要的编译器(例如g ++,clang,vc ++ ......)不遵守这个规则.见现场演示.

但我相信大多数人(包括我)会对当前不符合标准的行为感到高兴.如果编译器遵循标准,许多桥接C和C++的代码将被破坏.

考虑这个例子:

库提供C API:

#ifdef __cplusplus
extern "C" {
#endif
void registerCallbackInC(void(*callback)(void*));
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)

要在C++中使用库:

void f1(void*)
{
    ...
}

extern "C" void f2(void*)
{
    ...
}

registerCallbackInC(f1); // invalid, f1 has C++ linkage
registerCallbackInC(f2); // OK
Run Code Online (Sandbox Code Playgroud)

要使用registerCallbackInC,callback必须有C-linkage,但是,我们不能使用extern "C"模板:

extern "C"
{
    template<class T>
    void f(void*); // invalid …
Run Code Online (Sandbox Code Playgroud)

c++ templates linkage language-lawyer

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

std :: allocator是否在C++ 17中处理过度对齐的类型?

C++ 17引入了std::aligned_alloc对齐感知new,它可以进行过度对齐的分配,但是呢std::allocator?它是否处理过度对齐的类型?

c++ memory-alignment allocator c++17

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