标签: noexcept

C++17:将函数 noexcept 说明符推导为非类型参数

我注意到 MSVC 有时无法推导出其他编译器接受的非类型参数,最近遇到了一个涉及函数 noexcept 说明符的简单示例(自 C++17 以来,它是函数签名的一部分):

template <typename T> struct is_nocv_method : public std::false_type { };

template <typename ReturnT, typename ClassT, bool IsNoexcept, typename... Args>
struct is_nocv_method<ReturnT (ClassT::*)(Args...) noexcept(IsNoexcept)> : std::true_type { };

Run Code Online (Sandbox Code Playgroud)

Godbolt 建议 gcc 12.1 和 clang 14.0 毫无问题地接受这一点,但 MSVC 14.31 (cl.exe 19.31) 无法编译,声称IsNoexcept无法推断。这是编译器缺陷吗?

演示

c++ templates noexcept c++17

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

我应该在实现非投掷交换时使用throw()吗?

在实现非投掷交换习语时,我应该使用throw()吗?

namespace A
{
   struct B
   {
     void swap( B& other ) throw()
     { /* fancy stuff that doesn't throw */ }
   };

   void swap( B& lhs, B& rhs ) throw()
   { lhs.swap(rhs); }
}

namespace std
{
   template<>
   void swap( A::B& lhs, A::B& rhs ) throw()
   { lhs.swap(rhs); }
}
Run Code Online (Sandbox Code Playgroud)

特别是我担心将throw()规范放在专业化上std::swap.

额外问题:
使用C++ 0x的noexcept关键字时,答案是否有所不同?

c++ swap noexcept

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

为什么std智能指针类型析构函数不会继承指向对象的noexcept dtor状态

在C++ 11中,我的理解是默认情况下析构函数是隐式的noexcept(true),除了:

如果我有一个C明确标记了析构函数的类noexcept(false)(可能是因为它因某些奇怪的原因而抛出,我知道你不应该这样做,以及为什么)那么派生自C或包含类型成员的任何类的析构函数C也成了noexcept(false).

然而,其中包含了一个类std::shared_ptr<C>显然并不自动拥有它的析构函数切换到noexcept(false),并且同样适用于含有std::weak_ptr<C>,std::unique_ptr<C>等等.

这是一个完整的例子:

#include <type_traits>
#include <memory>

struct Normal {
    ~Normal() {
    }
};

struct ThrowsInDtor {
    ~ThrowsInDtor() noexcept(false) {
        throw 42;
    }
};

template<typename T>
struct Wrapper {
    T t;
};

template<typename T>
struct UniquePtrWrapper {
    std::unique_ptr<T> t;
};

template<typename T>
struct SharedPtrWrapper {
    std::shared_ptr<T> t;
};

static_assert(std::is_nothrow_destructible<Normal>::value, "A"); // OK
static_assert(!std::is_nothrow_destructible<ThrowsInDtor>::value, "B"); // OK

static_assert(std::is_nothrow_destructible<Wrapper<Normal>>::value, "C"); …
Run Code Online (Sandbox Code Playgroud)

c++ destructor smart-pointers noexcept c++11

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

std :: chrono :: ... :: time_point上的构造函数应该是noexcept吗?(或者他们为什么不呢?)

我在尝试保持原子time_point时遇到了这个问题,请参阅(原子需要noexcept默认构造函数,如果默认构造函数可用):http://cplusplus.github.io/LWG/lwg-active.html#2165

简单的问题是std :: atomic或类似的将无法在当前std下编译.

考虑到std :: chrono :: clock_type :: now()s是noexcept.似乎奇怪的是,时间点本身并非如此.

c++ atomic noexcept c++-chrono

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

如何在类noexcept之外定义默认构造函数?

我知道标记为的构造函数将尽可能=default"尝试" noexcept.但是,如果我在类之外定义它,它就noexcept不再存在了,正如您可以从此代码中看到的那样:

#include <iostream>
#include <utility>
#include <type_traits>

struct Bar
{
    Bar() = default;
    Bar(Bar&&) = default; // noexcept
};

struct Foo
{
    Foo() = default;
    Foo(Foo&&);
};
// moving the definition outside makes it noexcept(false)
Foo::Foo(Foo&&) = default; // not noexcept anymore

int main()
{
    Foo foo;
    Bar bar;
    std::cout << std::boolalpha;
    // checks
    std::cout << std::is_nothrow_move_constructible<Bar>::value << std::endl;
    std::cout << std::is_nothrow_move_constructible<Foo>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

如何=default在类外部定义这样的构造函数并制作它noexcept?为什么这样的构造函数noexcept(false)在类外定义?通过智能指针实现 …

c++ default-constructor noexcept c++11

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

禁用异常和noexcept()

std::swap 以这种方式声明:

template <class T> void swap (T& a, T& b)
    noexcept (is_nothrow_move_constructible<T>::value && 
              is_nothrow_move_assignable<T>::value);
Run Code Online (Sandbox Code Playgroud)

如果我在我的程序中禁用异常(比如使用-fno-exceptionsfor g ++)std::swap,如果它们是移动启用的,那么无论它们是否为noexcept,我都会使用自定义类型的移动操作?

编辑:后续问题:

在意识到std :: swap将始终使用移动时,如果我的类型有它们,我真正的问题是会发生什么样的特征is_nothrow_move_assignable<>

std::vector重新分配的时候,如果我的类型始终使用移动noexcept(true)的移动操作?

c++ g++ noexcept c++11

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

为什么std :: map find()没有被声明为noexcept?

C++ 14标准定义了find()成员函数,std::map如下所示:

iterator find(const key_type& x);
const_iterator find(const key_type& x) const;
Run Code Online (Sandbox Code Playgroud)

为什么这些功能没有定义为noexcept?内部可能出错的地方,需要抛出一个异常或产生未定义的行为(除了没有找到一个元素,在这种情况下函数返回一个end迭代器并且无论如何都不需要抛出异常)?

c++ dictionary exception-specification noexcept

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

将函数指针强制转换为noexcept指定的函数指针

说我有这些声明:

using fp_type = void(*)();
using fp2_type = void(*)() noexcept;
Run Code Online (Sandbox Code Playgroud)

void func(){}
fp_type fp(func);
Run Code Online (Sandbox Code Playgroud)

演员fp2_type(fp)表现良好吗?反过来(将noexcept指定的函数指针强制转换为没有noexcept说明符的函数指针)?

c++ function-pointers noexcept

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

noexcept函数返回一个抛出析构函数的类

在下面的代码中,我认为断言不应该触发,但确实如此.

struct A
{
  ~A() noexcept(false);
};

A f() noexcept;

int main()
{
  static_assert(noexcept(f()), "f must be noexcept");
}
Run Code Online (Sandbox Code Playgroud)

该函数f()显然是noexcept,但noexcept(f())被评估为false.(在gcc和clang中)

我错过了什么或者它是一个错误?

c++ noexcept c++11

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

如何正确推导出一个函数的noexcept-ness?

在通用上下文中,我们经常写类似的东西

return_type f(arg_type1 arg1, ...)
  noexcept(noexcept(statement_1) && noexcept(statement_2) && ... && noexcept(statement_n))
{
  statement_1;
  statement_2;
  ...
  statement_n;
}
Run Code Online (Sandbox Code Playgroud)

当a statement_k是return语句时,事情并非如此简单.这是不可能写的noexcept(return expr).相反,我应该理解当我们说return expr并分解成几个时发生的事情noexcept(something).但它似乎非常重要.

我想出了类似下面的算法:

  1. 如果return_type是参考类型,那么当然noexcept(expr)就足够了.
  2. 如果return_type不是参考类型,但如果return expr是保证复制省略发生的情况,那么再次noexcept(expr)就足够了.
  3. 否则,noexcept(expr) && std::is_nothrow_move_constructible<return_type>::value && std::is_nothrow_destructible<return_type>::value.

这样对吗?或者有更简单的方法吗?案例1将被归入案例3的特例,但案例2和案例3如何?

c++ noexcept copy-elision c++17

6
推荐指数
0
解决办法
108
查看次数