标签: noexcept

是否应该在传递函数指针时转发关于noexcept-ness的知识?

我编写了以下代码来测试noexcept函数调用之间的传播,它似乎不像我想象的那样工作.在GCC 4.7.2中,可以有效地测试一个函数,noexcept不仅仅是直接或作为模板特化参数传递; 但不是作为参数传递给模板化函数,或作为函数指针传递给普通函数 - 即使该函数声明其形式参数为noexcept.这是代码:

#include <iostream>

#define test(f) \
    std::cout << __func__ << ": " #f " is " \
              << (noexcept(f()) ? "" : "not ") \
              << "noexcept\n";

template <void(*f)()>
static inline void test0() {
    test(f);
}

template <typename F>
static inline void test1(F f) {
    test(f);
}

static inline void test2(void(*f)()) {
    test(f);
}

static inline void test3(void(*f)()noexcept) {
    test(f);
}

void f1() {}
void f2() noexcept {} …
Run Code Online (Sandbox Code Playgroud)

c++ noexcept c++11

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

std :: move_if_noexcept的基本原理仍在移动投掷仅移动类型?

move_if_noexcept 将:

  • 返回一个rvalue - 促进移动 - 如果移动构造函数是noexcept 或者没有复制构造函数(仅移动类型)
  • 返回一个左值 - 强制复制 - 否则

我发现这个相当令人惊讶,因为只有移动类型的投掷移动器仍然会有这个移动 - 由使用的代码调用move_if_noexcept.

有没有给出一个彻底的理由呢?(可能直接或在N2983之间?)

不编码会不会更好,而不是仍然不得不面对不可恢复的移动场景?vectorN2983中给出的示例很好:

void reserve(size_type n)
{
  ... ...
                 new ((void*)(new_begin + i)) value_type( std::move_if_noexcept( (*this)[i]) ) );
        }
        catch(...)
        {
            while (i > 0)                 // clean up new elements
               (new_begin + --i)->~value_type();

            this->deallocate( new_begin );    // release storage
            throw;
        }
*!*     // -------- irreversible mutation starts here -----------
        this->deallocate( this->begin_ );
        this->begin_ = new_begin;
        ... ...
Run Code Online (Sandbox Code Playgroud)

标记线中给出的注释实际上是错误的 …

c++ move-semantics noexcept

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

为什么std :: vector使用移动构造函数,尽管声明为noexcept(false)

无论我在互联网上阅读什么,强烈建议如果我希望我的班级能够很好地使用std::vector(即从我的班级移动语义std::vector),我应该将构造函数移动为"noexcept"(或noexcept(true)).

为什么std::vector使用它,即使我将其标记noexcept(false)为实验?

#include <iostream>
#include <vector>
using std::cout;

struct T
{
    T() { cout <<"T()\n"; }

    T(const T&) { cout <<"T(const T&)\n"; }

    T& operator= (const T&)
    { cout <<"T& operator= (const T&)\n"; return *this; }

    ~T() { cout << "~T()\n"; }

    T& operator=(T&&) noexcept(false)
    { cout <<"T& operator=(T&&)\n"; return *this; }

    T(T&&) noexcept(false)
    { cout << "T(T&&)\n"; }
};

int main()
{
    std::vector<T> t_vec;
    t_vec.push_back(T());
}
Run Code Online (Sandbox Code Playgroud)

输出:

T()
T(T&&) …
Run Code Online (Sandbox Code Playgroud)

c++ vector move-semantics noexcept c++11

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

在哪种情况下std :: unique_ptr :: operator []会抛出?

我有一个operator[]为我的班级,它所做的只是呼吁std::unique_ptr::operator[]一个unique_ptr成员.相关部分就是这样:

template <typename T> struct Foo {
    T& operator [](const size_t pos) const noexcept
    {
        return data_[pos];
    }

    std::unique_ptr<T[]> data_;
};
Run Code Online (Sandbox Code Playgroud)

我已将运营商标记为noexcept.然而,unique_ptr::operator[]不是 noexcept.我无法找出原因,以及我是否可以假设它永远不会抛出.unique_ptr::operator[]本身没有列出文档中的任何异常(cppreference和MSDN声称它没有定义它可能抛出的任何异常列表.)

所以我假设缺失noexcept可能是:a)错误,或b)运算符访问的基础数据类型可能抛出.选项a会很好,因为这意味着我可以标记自己的运算符noexcept.选项b很难理解,因为所有操作员都会获得参考,并且它不会调用任何东西.

所以,长话短说,是否有任何unique_ptr::operator[]抛出的可能性,从noexcept函数中调用它是否安全?

c++ unique-ptr language-lawyer noexcept c++11

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

为什么允许在noexcept-tagged函数中抛出异常?

我很难理解这一点.

double compute(double x, double y) noexcept
{
   if (y == 0)
       throw std::domain_error("y is zero");
   return x / y;
}
Run Code Online (Sandbox Code Playgroud)

这在clang中编译得很好(我没有检查过gcc),但这对我来说似乎是胡说八道.为什么编译器允许noexcept函数包含throw语句?

c++ tags compilation exception noexcept

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

重载 noexcept 难道没有意义吗?

我试图了解 noexcept 功能。我知道这可能会令人困惑,但除此之外,如果可能的话,不能从调用函数中推导出来。

这是这种情况的非工作示例,

void f(){}
void f() noexcept{} // not allowed in c++

void g(){f();} // should call f
void h() noexcept{f();} // should call f noexcept
int main(){
    g();
    h();
}
Run Code Online (Sandbox Code Playgroud)

如果调用函数 ( h) 中没有 try/catch 块,那么编译器可以推断出有人对调用特定的 f 感兴趣。

此模式是否以其他解决方法形式使用?

我所能想象的就是这样的东西,但它不是很通用:

template<bool NE> void F() noexcept(NE);

template<>
void F<true>() noexcept(true){}
template<>
void F<false>() noexcept(false){}

void g(){F<noexcept(g)>();} // calls F<false>
void h() noexcept{F<noexcept(h)>();} // call F<true>
Run Code Online (Sandbox Code Playgroud)

有些人可能想知道为什么这会有意义。我的逻辑是,C++ 允许重载const函数参数和成员函数。 const例如,成员函数更喜欢调用const成员重载。

我认为noexcept函数调用noexcept …

overloading overload-resolution noexcept c++11 c++17

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

std :: vector默认构造函数是否可以抛出异常

如果我std::vector使用默认构造函数(和默认分配器)构造一个空,它可以抛出异常吗?

通常,为容器的元素分配空间可以抛出异常(这将是一个异常std::bad_alloc).但一个默认的构造函数std::vector并不需要分配任何这样的空间.它可以在第一次插入或赋值时懒惰地分配一些空间.但是C++标准是否要求它不会抛出异常(暗示延迟分配,或者捕获std::bad_alloc然后再回到延迟分配)?

c++ stdvector bad-alloc noexcept

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

C++14 中 noexcept 说明符的奇怪行为

noexcept在 C++14 中发现了一个奇怪的操作符行为。以下代码可以通过 gcc 和 clang(使用 --std=c++14 选项)很好地编译。

// test.cpp
#include <iostream>
#include <type_traits>

#if 1
#define TESTREF(X) X&&
#else
#define TESTREF(X) X const&
#endif

template <class F, class... Args>
struct is_noexcept_callable
    : public std::conditional_t<noexcept(std::declval<F>()(std::declval<Args>()...)), std::true_type, std::false_type> {};

template <
    class F,
    std::enable_if_t<is_noexcept_callable<F,int>::value,int> = 0
    >
int evalInt(int x, TESTREF(F) f) noexcept
{
    return static_cast<int>(f(x));
}

template <
    class F,
    std::enable_if_t<!is_noexcept_callable<F,int>::value,int> = 0
    >
int evalInt(int x, TESTREF(F) f)
{
    return static_cast<int>(f(x));
}

int id(int x) noexcept { …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer noexcept c++14

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

非抛出函数指针可以指向抛出函数吗?

在关于异常规范的 C++ Primer 上noexcept,据说指向可能抛出隐式(没有异常规范定义,例如:)void(*p)();或显式(void(*p)() noexcept(false);)的函数的指针可以指向任何函数,甚至指向不抛出的函数。

另一方面,一个不能抛出异常的函数指针(noexcept例如void(*p) noexcept;)只能指向一个不会抛出异常的函数。

我发现这非常合乎逻辑,因为第一个指针可以从抛出函数指针指向非抛出函数,而第二个指针也很合乎逻辑。

我尝试过这个来了解更多:

void func1(){ // may throw
    std::cout << "func1()\n";
}

void func2() noexcept(false){ // may throw
    std::cout << "func2()\n";
}

void func3() noexcept(true){ // won't throw
    std::cout << "func3()\n";
}

void func4() noexcept{ // won't throw
    std::cout << "func4()\n";
}


int main(int argc, char* argv[]){

    void(*pFn1)();
    pFn1 = func1; // OK
    pFn1 = func2; // OK
    pFn1 = func3; // OK
    pFn1 …
Run Code Online (Sandbox Code Playgroud)

c++ function-pointers noexcept

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

三元运算符应用于不同的 lambda 会产生不一致的结果

考虑以下内容,它使用三元运算符来获取两个 lambda 的公共函数指针类型

int main() {
  true ? [](auto) noexcept {} : [](int) {};
}
Run Code Online (Sandbox Code Playgroud)

GCC-trunk 仅在 C++14 中接受它,但在 C++17/20 中拒绝它(演示):

<source>:2:8: error: operands to '?:' have different types 'main()::<lambda(auto:1)>' and 'main()::<lambda(int)>'
    2 |   true ? [](auto) noexcept {} : [](int) {};
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

Clang-trunk 在所有 C++14/17/20 模式下接受它(演示)。

MSVC-trunk 仅在 C++20 中接受它,但在 C++14/17 中拒绝它(演示):

<source>(2): error C2446: ':': no conversion from 'main::<lambda_01e5bb79b5a210014fb78333f6af80f9>' to 'main::<lambda_57cf6f5767bc1bee4c1e1d9859a585d2>'
<source>(2): note: No user-defined-conversion operator available that can perform this …
Run Code Online (Sandbox Code Playgroud)

c++ lambda language-lawyer noexcept c++20

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