考虑以下功能:
// Declaration in the .h file
class MyClass
{
template <class T> void function(T&& x) const;
};
// Definition in the .cpp file
template <class T> void MyClass::function(T&& x) const;
Run Code Online (Sandbox Code Playgroud)
noexcept如果类型T不是可构造的,我想创建此函数.
怎么做 ?(我的意思是什么语法?)
有问题的代码是
#include <functional>
#include <utility>
template <typename F>
void for_each(F&&) noexcept {}
template <typename F, typename T, typename... Us>
void for_each(F&& f, T&& v, Us&&... us) {
std::invoke(std::forward<F>(f), std::forward<T>(v));
for_each(std::forward<F>(f), std::forward<Us>(us)...);
}
void func(void*) noexcept {}
int main() {
for_each(func, nullptr);
}
Run Code Online (Sandbox Code Playgroud)
它在gcc 8上编译,但在clang 6上失败,出现以下错误:
/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4198:19: error: invalid application of 'sizeof' to a function type
static_assert(sizeof(_Tp) > 0, "Type must be complete.");
^~~~~~~~~~~
/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4203:15: note: in instantiation of template class 'std::__1::__check_complete<void (void *) noexcept>' …Run Code Online (Sandbox Code Playgroud) 可以noexcept修改应用于lambda表达式?如果是这样,怎么样?
可以noexcept对函数参数进行约束吗?例如,类似于下面的代码,其中的含义是回调函数必须是noexcept?
//probably not valid code - I'm just trying to express the idea
void f_async(std::function<void (int) noexcept> callback) noexcept
{
...
}
Run Code Online (Sandbox Code Playgroud)
这几乎可以通过以下代码完成,但我想知道是否有办法使用类似上面的替代方法.
void f_async(std::function<void (int)> callback)
noexcept(callback(std::declval<int>()))
{
...
}
Run Code Online (Sandbox Code Playgroud)
当然这里的问题是,f_async可能是noexcept(false),如果回调是noexcept(false)-我想要一个更强有力的声明,f_async是永远 noexcept,这意味着如果你使用它只是调用noexcept回调函数.
考虑以下程序:
#include <type_traits>
struct Thrower
{
~Thrower() noexcept(false) { throw 1; }
};
struct Implicit
{
Thrower t;
};
static_assert(!std::is_nothrow_destructible<Implicit>::value, "Implicit");
struct Explicit
{
~Explicit() {}
Thrower t;
};
static_assert(!std::is_nothrow_destructible<Explicit>::value, "Explicit");
Run Code Online (Sandbox Code Playgroud)
有g++-4.8.1,静态断言失败Explicit- 它似乎认为~Explicit()是noexcept.这与我的期望不符.根据§12.4.3:
没有异常规范的析构函数的声明被隐式地认为具有与隐式声明相同的异常规范
这里有趣的是Implicit根据我对§15.4.14(通过§12.4.7)的解释,检查似乎表现得很好.
...如果f是...析构函数...它是隐式异常 - 规范指定...
noexcept(true)如果它直接调用的每个函数都不允许例外,则f具有异常规范.
g++-4.7缺乏is_nothrow_destructable,我写了自己检查4.7中的行为.该程序似乎编译得非常好.我保留完全错误的权利和我的困惑的来源:
template <typename T>
struct is_nothrow_destructible
{
static constexpr bool value = noexcept(std::declval<T>().~T());
};
Run Code Online (Sandbox Code Playgroud)
TL; DR:为什么g++-4.8.1认为没有异常规范的显式声明的析构函数总是如此 noexcept(true)?
更新:我在此打开了一个错误:57645 …
移动赋值运算符通常应声明为noexcept(即将类型存储在STL容器中).但是复制和交换习惯用法允许在一段代码中定义复制和移动赋值运算符.在这种情况下如何处理noexcept说明符?复制结构可以抛出,但我怀疑它是否可以违反noexcept说明符.
// Is it correct considering that T copy constructor can throw?
T& operator=(T other) noexcept;
Run Code Online (Sandbox Code Playgroud) 特别是std::vector与其相关的是,类型noexcept在可能的情况下是可移动的.
所以在声明= default像in 的移动构造函数时
struct Object1
{
Object1(Object1 &&other) = default;
};
Run Code Online (Sandbox Code Playgroud)
std::is_nothrow_move_constructible<Object1>::value将是true每个成员(0在这里)Object1是nothrow-move-constructible,这在这里得到解答.
然而,如果仅声明移动复制构造函数,然后= default在以下代码中进行定义,会发生什么?
struct Object2
{
Object2(Object2 &&other);
};
Object2::Object2(Object2 &&other) = default;
Run Code Online (Sandbox Code Playgroud)
随着G ++ 4.9.2 std::is_nothrow_move_constructible<Object2>::value是false,我要纪念这两个声明和定义noexcept,使其true.
现在我感兴趣的是实际规则是什么.特别是因为有效的现代C++中的第22项(Scott Meyers)似乎通过建议像我一样实现了pimpl-idiom移动构造函数来提供错误的建议Object2.
如果我将一个函数标记为noexcept(false),或任何其他评估为false的表达式,它意味着什么?(1)我是否向编译器确保该函数可以抛出异常?,(2)或者我是否确定它是否可以抛出异常?
最后,如果省略说明noexcept符,它等同于noexcept(false)或仅等同于上述的(2)nd含义?
根据C++标准,C++标准库的实现是否允许加强标准noexcept定义的方法和C++标准库的其他功能?
例如,如果C++标准指定了一些函数,std::f那么void f();允许实现它的标准库实现void f() noexcept;呢?
这是一个关于我的问题的例子:
struct B {
B(B&&, int = (throw 0, 0)) noexcept {}
};
Run Code Online (Sandbox Code Playgroud)
我知道这是一段非常奇怪的代码。它只是用来说明问题。的移动构造函数B有一个noexcept说明符,而它有一个抛出异常的默认参数。
如果我使用noexcept运算符来测试移动构造函数,它将返回false. 但是,如果我提供第二个参数,它将返回“true”(在 GCC 和 Clang 上):
noexcept( B(std::declval<B>()) ); // false
noexcept( B(std::declval<B>(), 1) ); // true
Run Code Online (Sandbox Code Playgroud)
然后我添加了 class D,它继承自B但不提供移动构造函数。
struct D : public B { };
Run Code Online (Sandbox Code Playgroud)
我测试了类D:
noexcept( D(std::declval<D>()) ); // true
Run Code Online (Sandbox Code Playgroud)
我已经阅读了标准,我认为根据标准,noexcept( D(std::declval<D>()) )应该返回false.
现在我试着按照标准来分析结果。
noexcept运算符的结果是,true除非表达式可能抛出([except.spec])。
所以现在我们需要判断表达式是否B(std::declval<B>())是 …
代码:
struct T { T() {} };
struct S
{
T t;
S() noexcept = default;
};
int main()
{
// S s;
}
Run Code Online (Sandbox Code Playgroud)
g ++ 4.9.2接受此但没有错误或警告,但第7行的clang 3.6和3.7报告:
error: exception specification of explicitly defaulted default constructor does not match the calculated one
Run Code Online (Sandbox Code Playgroud)
但是,如果该行S s;未被注释掉,g ++ 4.9.2现在报告:
noex.cc: In function 'int main()':
noex.cc:12:7: error: use of deleted function 'S::S()'
S s;
^
noex.cc:7:5: note: 'S::S() noexcept' is implicitly deleted because its exception-specification does not match the implicit exception-specification '' …Run Code Online (Sandbox Code Playgroud)