小编Wal*_*ter的帖子

应该std :: vector honor alignof(value_type)?

如果我定义一个具有特定对齐要求的简单类型,那么std::vector<t>所述类型的a是否应该遵循每个元素的对齐?

请考虑以下示例

typedef std::array<double,3> alignas(32) avx_point;
std::vector<avx_point> x(10);
assert(!(std::ptrdiff_t(&(x[0]))&31) &&   // assert that x[0] is 32-byte aligned
       !(std::ptrdiff_t(&(x[1]))&31));    // assert that x[1] is 32-byte aligned
Run Code Online (Sandbox Code Playgroud)

我发现对齐要求是默认(没有任何警告)被clang 3.2(有或没有)违反-stdlib=libc++,而gcc 4.8.0发出一个警告,它忽略了模板参数的属性std::vector(intel编译器太愚蠢了解alignas,但如果我使用__declspec(align(32))它,它的行为就像clang).两者都创建触发断言的代码.

那么,这是正确的行为还是clang(和icpc)的错误以及gcc的问题?

编辑 以回答评论中提出的问题:如果我定义

typedef typename std::aligned_storage<sizeof (avx_point),
                                      alignof(avx_point)>::type avx_storage;
Run Code Online (Sandbox Code Playgroud)

我明白了

sizeof (avx_storage) == 32;
alignof(avx_storage) == 32;
Run Code Online (Sandbox Code Playgroud)

但是std::vector<avx_storage>仍然无法对齐clang和gcc的第一个元素(因此也是所有其他元素)(这次没有警告).因此,实现显然存在两个问题:首先,std::allocator<type>即使对于第一个元素(非法?),也忽略了任何对齐要求;其次,没有应用填充来确保后续元素的对齐.

c++ containers alignment c++11

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

如何将属性添加到lambda函数?

假设我有一个lambda

auto func = [](std::string msg) { throw std::runtime_error(msg); };
Run Code Online (Sandbox Code Playgroud)

(诚​​然,这个例子没什么意义,但那不是重点).如果这不是lambda,而是普通函数,我会用noreturn属性声明它

[[noreturn]] void func(std::string msg) { throw std::runtime_error(msg); }
Run Code Online (Sandbox Code Playgroud)

这也可以用于lambda吗?(我用clang 3.5尝试了几种变体,但没有任何成功.)


编辑使用Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn),我试过了

auto func = [](std::string msg) -> [[noreturn]] void { throw std::runtime_error(msg); };
Run Code Online (Sandbox Code Playgroud)

要么

auto func = [](std::string msg) [[noreturn]] { throw std::runtime_error(msg); };
Run Code Online (Sandbox Code Playgroud)

但两人都被拒绝了.这是clang 3.5的不完整/错误吗?

c++ lambda attributes noreturn

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

有没有办法检查宏的非数字值

假设我有

#define Name Joe
Run Code Online (Sandbox Code Playgroud)

有没有办法区分宏的不同值.以下不起作用,但你明白了

#if   Name==Joe
// some code
#elif Name==Ben
// some alternative code
#endif
Run Code Online (Sandbox Code Playgroud)

我想用它来生成来自相同源代码的各种目标文件.源差异很小,因此可以很容易地进行宏观控制.宏将通过-DName=Joe编译器标志传入.另请注意,这Name将是一个实际的符号名称,因此我们不能使用基于#define Joe 1等的技巧.


强制编辑请注意,这个类似的问题实际上处理的是字符串值宏.而且那里的答案没有帮助.接受的答案避免了问题(但没有解决),另一个答案strcmp在宏中使用,它依赖于扩展等.

macros c-preprocessor preprocessor-directive

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

函数参数的类型是否可以推导?

我有一个使用返回码的类:

class MyClass
{
    // ...

public:
    // ValueType get_value() const;               // usual code
    ErrorCode get_value(ValueType& value) const;  // uses error code

   // ...
};
Run Code Online (Sandbox Code Playgroud)

因此,第二种形式get_value()实际上将值作为函数参数提供,而不是作为返回值.

是否有可能推断出函数参数的类型get_value(),也许使用 decltype

int main()
{
    // ...

    MyClass my_class;
    // auto val = my_class.get_value();  // okay: value has correct type

    declytype( /* something here */ ) value;
    const auto error = my_class.get_value( value );

    // ...
}
Run Code Online (Sandbox Code Playgroud)

c++ decltype return-type-deduction

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

哪些设计考虑证明std :: make_heap()显然是次优的?

根据cppreference(在C++标准的条件)std::make_heap()采用至多3N比较,但根据维基百科不超过2n个实际需要比较.

在明显次优的规范背后有什么设计考虑因素(如果有的话)?

是否有可能与交换操作进行交易比较的算法,即以更多比较的价格(平均)可以做更少的掉期?


对于那些希望以意见为基础的人来说:我已经编辑了帖子,以避免它基于意见,通过遵循这个关于元的建议并避免为什么我们有这样的语言功能?问题,而是准确地问我想知道什么.如果你仍然认为,这是基于意见的,请建议如何解决这个问题.

c++ algorithm heap

7
推荐指数
0
解决办法
138
查看次数

检查从enable_shared_from_this派生的对象是否由shared_ptr管理?

假设我有一个派生自的类 std::enable_shared_from_this

struct foo
  : std::enable_shared_from_this<foo>
{
    std::shared_ptr<foo> get_shared()
    {
        return shared_from_this();
    }

    bool is_shared() const
    {
        /* implementation ??? */
    }
};

foo  A;
auto S= A.get_shared();   // UB (pre c++17) or exception (c++17)
Run Code Online (Sandbox Code Playgroud)

在c ++ 17之前,似乎无法检测对象foo是否实际由a管理shared_ptr.正确?

但即使对于c ++ 17,我也不确定如何最好地实现这样的检测.一个明显的方法是

bool foo::is_shared() const
{
    try {
        shared_from_this();
    } catch(...) { 
        return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

但可以try- catch避免?我可以用weak_from_this()吗?怎么样?

c++ shared-ptr c++11 c++17

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

为什么std :: vector这么快(或者我的实现太慢了)

前几天我正在玩,试图看看我可以在多大程度上优化某些东西.我决定从一个简单的地图开始,只是进行线性搜索,找出是否存在元素,然后尝试优化其中的大部分.另外,为了比较,我使用std :: find对std :: map和std :: vector做同样的事情.

地图的结果是预期的,比我的地图更慢的创建和破坏,但更快的速度(实际上,我无法测量它,它总是返回0).问题出在std :: vector上.我希望它比我的实现慢,但不是,我真的不明白它是如何相同或更快,因为我的实现正在跳过最坏的情况(值不在向量中)并且是使用结果缓存.

谁能在这里解决一些问题?我知道stl背后的人是半神,但仍然没有意义.

基准测试结果(i3,Windows 8.1 Pro 64,Visual Studio 2013):

std::vector :
    Build : 85.0042 ms
    Loop : 37.0011 ms
    Find : 1.82259 ms  -> First : Found, Second : Found, Third : Not Found
    Release : 0 ms
--------------------
std::map :
    Build : 6929.41 ms
    Loop : 570.032 ms
    Find : 0 ms  -> First : Found, Second : Found, Third : Not Found
    Release : 1425.08
--------------------
Linear Map V0:
    Build …
Run Code Online (Sandbox Code Playgroud)

c++ performance stl c++11

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

选择什么标准容器(如果有的话)?

我需要一些内存管理,并希望我可以将它建立在一些std容器上.我的要求是:

  1. 元素只有一个默认的构造函数(没有副本,没有移动,没有其他)
  2. 容器可以通过一小块连续的元件扩展(在后面)
  3. 我甚至大致知道我需要多少元素,甚至更好,在任何时候我最终需要多少元素.但这些都是估计数.
  4. 我真的不需要迭代器,但获取元素运行数的方法会很方便.

所以,我需要一些可以通过添加块来扩展的东西,比如std::deque.但是std::deque,我不能保证通过8个元素进行扩展会给我一个连续的块.而且std::deque没有,capacity所以我无法"适应" std::deque.

这意味着我必须自己写,对吗?(注意:我不想知道如何写我自己的,但只有我必须).

编辑澄清:只有在每次扩展时获得的元素块必须是连续的,而不是整个容器 - 这显然与其他要求相矛盾.

编辑为jalf所以这是什么:用于"排序"3D点的空间八度树.树节点指的是立方体单元,并形成与使用指针链接的父母和女儿的链接结构.同级节点未链接,但在内存中相邻.事先不知道节点的总数(因为每个最终节点的点数> 1),但是可以获得估计.在树构建期间,当划分非最终节点时,必须获得最多8个新节点的连续块,然后将其链接到树中.移动或复制这些节点会使任何现有链接(指针)无效.

另一个编辑只是为了澄清一些讨论.任何基于的设计都std::vector<T>不得使用resize()和/或reserve().两者都需要T在某些条件下复制或移动构造函数.即使从未在这些条件下调用过,代码也无法编译.

c++ containers memory-management

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

如何用`decltype`和继承规避英特尔C++编译器的问题?

今天我非常惊讶地发现英特尔的icpc(版本14.0.2,使用std=c++0x)无法编译以下代码段.


#include <type_traits>

namespace traits_tests {
  template<typename>
  struct sfinae_true : std::true_type {};

  template<typename T>
  static auto value_type(int) -> sfinae_true<typename T::value_type>;
  template<typename T>
  static auto value_type(void*) -> std::false_type;
}

template<typename C>
struct has_value_type
  : decltype(traits_tests::value_type<C>(0)) {};
Run Code Online (Sandbox Code Playgroud)

抱怨最后一行:

inc/traits.h(258): error: expected an identifier
    : decltype(traits_tests::value_type<C>(0)) {};
      ^
Run Code Online (Sandbox Code Playgroud)

代码适用于clanggcc.

我真的不想完全重写,以使它与有缺陷的编译器一起工作(为什么商业编译器总是有缺陷?).

  • 是否有一种更简单的方法,而不是完全不同的SFINAE模式,以使其适用icc

编辑:是的,我知道icc支持decltype一段时间以来.但在上述特定背景下,icc未能支持它.另请注意,使用std=c++11而不是std=c++0x没有区别.

c++ inheritance icc decltype c++11

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

在C++中封装大量参数14

我想写它使用许多参数,我将调用一个函数a,bc.我有四种在C++ 14中实现它的选择.

对于2018年的新现代C++项目,其中一种风格最符合ISO C++的理念?其他风格指南推荐哪些款式?

面向对象的风格

class Computer {
    int a, b, c;
public:
    Computer(int a, int b, int c) : a(a), b(b), c(c) {}
    int compute(int) const {
        // do something with a, b, c
    }
};
...
const Computer computer(a, b, c);
int result = computer.compute(123);
Run Code Online (Sandbox Code Playgroud)

优点:

  • 易于C++程序员掌握

缺点:

  • 要计算地图或折叠操作中的内容,我们必须做笨重的事情 [computer](int input){ return computer.compute(input); }

C风格

struct ComputeParams {
    int a, b, c;
};

int compute(const ComputeParams &params, int input) { …
Run Code Online (Sandbox Code Playgroud)

c++ oop encapsulation functional-programming c++14

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