小编Ser*_*eyA的帖子

C ++标准是否保证插入关联容器失败不会修改rvalue-reference参数?

#include <set>
#include <string>
#include <cassert>

using namespace std::literals;

int main()
{
    auto coll = std::set{ "hello"s };
    auto s = "hello"s;
    coll.insert(std::move(s));
    assert("hello"s == s); // Always OK?
}
Run Code Online (Sandbox Code Playgroud)

C ++标准是否保证插入关联容器失败不会修改rvalue-reference参数?

c++ stl rvalue-reference language-lawyer pass-by-rvalue-reference

32
推荐指数
2
解决办法
1041
查看次数

检查类型是否是模板的实例化

我想在编译期间检查类型是否是特定模板的实例化.

例如:

  1. std::vector<int> 实例化 std::vector
  2. std::array<int, 5> 实例化 std::array

我可以进行适用于案例1的测试,但不适用于案例2.

#include <iostream>
#include <type_traits>
#include <string>
#include <vector>
#include <array>
#include <queue>
template<template<typename...> class, typename...>
struct is_instantiation : public std::false_type {};

template<template<typename...> class U, typename... T>
struct is_instantiation<U, U<T...>> : public std::true_type {};

int main() {
    using A = std::vector<int>;
    std::cout << is_instantiation<std::vector, A>::value << "\n";
    std::cout << is_instantiation<std::queue, A>::value << "\n";
    // std::cout << is_instantiation<std::array, A>::value << "\n";
}
Run Code Online (Sandbox Code Playgroud)

如何让它适用于这两种情况?

我试过汽车,但无法使它工作.

C++中模板参数中auto的优点17

c++ templates auto c++17

23
推荐指数
1
解决办法
719
查看次数

析构函数可以在const对象上调用非const函数吗?

我搜索了这个问题的答案,却找不到答案.请考虑以下代码:

struct Foo
{
    int *bar;
    Foo(int barValue) : bar(new int(barValue)) {}
    ~Foo() { do_this(); }
    void do_this() { delete bar; bar = nullptr; }
};

int main()
{
    const Foo foo(7);
}
Run Code Online (Sandbox Code Playgroud)

do_this()不能在一个const对象上调用,所以我做不了类似的事情foo.do_this().在某些情况下do_this(),在析构函数之外调用也是有意义的,这就是为什么我不想简单地在析构函数定义中包含代码.因为do_this()修改成员变量,我不能将其声明为const.

我的问题是:将析构函数可以调用do_this()一个在const当对象被销毁的对象?

我尝试了它并没有收到任何错误,但我想确保一旦我的程序终止,我不会导致内存泄漏.

c++ destructor const language-lawyer

15
推荐指数
1
解决办法
378
查看次数

作为朋友的非模板类的模板成员

下面的代码片段由gcc,icc和msvc(最新的问题)精确编译,但是<source>:6:9: error: calling a private constructor of class 'B<int>'在标记的行中叮当作响.然而它适用于免费模板功能,如代码所示:

struct A {
    template<class T>
    static void create () {
        T();
    }
};

template<class T>
void create() {
    T();
}

template<typename T>
struct B {

    friend void A::create<B>();
    friend void create<B>();

    private:
    B() = default;
};

int main() {
     A::create<B<int>>(); // clang trips here
     create<B<int>>(); // fine!
}
Run Code Online (Sandbox Code Playgroud)

在此上下文中,非模板类的静态模板成员与自由模板函数之间可能有什么区别?

c++ templates language-lawyer

15
推荐指数
1
解决办法
504
查看次数

尽可能在编译时执行函数契约

(这个问题的灵感来自于如何生成编译错误以防止某些VALUE(非类型)进入函数?)

比方说,我们有一个单一的参数foo,语义定义为

int foo(int arg) {
    int* parg;
    if (arg != 5) {
        parg = &arg;
    }

    return *parg;
}
Run Code Online (Sandbox Code Playgroud)

上面的整个代码用于说明一个简单的想法 - 函数返回它自己的参数,除非参数等于5,在这种情况下行为是未定义的.

现在,挑战 - 以这种方式修改函数,如果它的参数在编译时已知,则应生成编译器诊断(警告或错误),如果不是,则在运行时仍未定义行为.解决方案可能依赖于编译器,只要它可以在四大编译器中的任何一个中使用.

以下是一些无法解决问题的潜在路线:

  • 使函数成为一个模板,将其参数作为模板参数 - 这不能解决问题,因为它使函数不适合运行时参数
  • 使函数成为一个constexpr- 这不能解决问题,因为即使编译器看到未定义的行为,它们也不会在我的测试中产生诊断 - 相反,gcc会插入ud2指令,这不是我想要的.

c++

13
推荐指数
1
解决办法
388
查看次数

为什么删除void*是UB而不是编译错误?

为什么通过void*未定义的行为而不是编译错误来删除对象?

void foo(void* p) {
    delete p;
}
Run Code Online (Sandbox Code Playgroud)

这段代码编译并生成代码,虽然gcc和clang上有警告(令人惊讶的是,ICC没有发出警告):

:2:5:警告:无法删除带有指针''''''的类型'void*'[-Wdelete-incomplete]

为什么不是简单的格式错误的程序,语法无效?貌似标准没有花太多时间就可以了,在说[expr.delete]

这意味着无法使用void*类型的指针删除对象,因为void不是对象类型.

我有什么理由不知道为什么这不会触发硬编译错误?

c++ void-pointers undefined-behavior language-lawyer delete-operator

10
推荐指数
1
解决办法
578
查看次数

在地图中使用unique_ptr时删除std :: pair中的函数

我有一段C++代码,我不确定它是否正确.请考虑以下代码.

#include <memory>
#include <vector>
#include <map>

using namespace std;

int main(int argc, char* argv[])
{
    vector<map<int, unique_ptr<int>>> v;
    v.resize(5);

    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

GCC编译这段代码没有问题.但是,英特尔编译器(版本19)因错误而停止:

/usr/local/ [...] /include/c++/7.3.0/ext/new_allocator.h(136): error: function "std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2> &) [with _T1=const int, _T2=std::unique_ptr<int, std::default_delete<int>>]" (declared at line 292 of "/usr/local/ [...] /include/c++/7.3.0/bits/stl_pair.h") cannot be referenced -- it is a deleted function
    { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
                            ^
      detected during:

[...]

instantiation of "void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type={std::size_t={unsigned long}}) [with _Tp=std::map<int, std::unique_ptr<int, std::default_delete<int>>, std::less<int>, std::allocator<std::pair<const int, std::unique_ptr<int, …
Run Code Online (Sandbox Code Playgroud)

c++ icc c++14

10
推荐指数
1
解决办法
621
查看次数

是否必须将"sockaddr_in"结构归零?

无论我到哪里,我都会看到以下代码:

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = ip;
Run Code Online (Sandbox Code Playgroud)

在C++中,同样的想法通常表示为

sockaddr_in addr = {}; // unneccesary(?) value-initialzation
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = ip;
Run Code Online (Sandbox Code Playgroud)

然而,在我设置这些成员之前,我没有看到(在官方文档方面)我有任何要求将结构清零!是的,通常BSD套接字实现做有一个sin_zero用于定义的成员sockaddr_in,但他们总是说需要进行填充成员,对齐的大小sockaddr_insockaddr.他们从不要求人们将任何具体内容放入其中.

有没有真正的,文件证明需要零出结构?

PS之前VTC问题的若干SO一个问题的有关副本memsetsockaddr_in,请确保该问题您所提出的建议为重复有正式文件,而不是"以防万一未使用成员的初始化"只是猜测的任何链接.

c c++ sockets language-lawyer

9
推荐指数
1
解决办法
1048
查看次数

map :: emplace在哪一点上创建了一个对象?

std::map::emplace在标准中以某种方式创建对象(即调用构造函数)的点是什么?如果是,是否检查此类密钥存在之前或之后发生?

在以下情况下,这很重要:

struct X {};
std::map<int, std::unique_ptr<X> > map;

void f(int x) {
    map.emplace(x, new X);
}
Run Code Online (Sandbox Code Playgroud)

如果首先创建对象,则一切都很酷(构造unique_ptr并拥有资源),但如果在检查后构造它,则在重复键的情况下存在内存泄漏.

所有我能在标准中找到的是

插入一个value_type对象t,使用std::forward<Args>(args)...if和仅当容器中没有元素且使用等效于t的键的元素构造 .

这没有解决我的问题.

c++ language-lawyer c++11

9
推荐指数
1
解决办法
714
查看次数

std :: set带字符串键和潜在的效率损失

假设我最简单std::set

std::set<std::string> my_set;
Run Code Online (Sandbox Code Playgroud)

现在,我有一个函数可以接受const char*并需要告诉我该字符串是否存在,以最直接的方式实现:

bool exists(const char* str) {
    return my_set.count(str) > 0;
}
Run Code Online (Sandbox Code Playgroud)

现在,这显然是效率损失。在这里无缘无故地发生(潜在的)动态内存分配,然后再进行释放。

我们该如何消除呢?我想与用作std::string键类型进行比较char*。一种方法是在unique_ptr<char>自定义比较器中使用而不是我的键类型,但是那样会很尴尬。

实际上,该问题可以推广到更广泛的情况,即“如何在不转换为键类型的情况下调用提供的类型的比较?”

PS我已经看过std :: string作为map键和map.find()的效率,但是我对答案不满意,这有效地重申了不需要这种优化,尽管这显然是错误的。

c++ string

9
推荐指数
1
解决办法
85
查看次数