【问题标题】:Recursive noexcept specification递归 noexcept 规范
【发布时间】:2014-07-09 11:45:41
【问题描述】:

用g++ 4.9和clang 3.4测试,为什么这段代码编译不出来:

namespace {

template<typename T>
constexpr auto f(T && t) noexcept {
    return true;
}

template<typename T, typename... Ts>
constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
    return f(ts...);
}

}   // namespace

int main() {
    f(true, 0, 5u);
}

但是这段代码可以:

namespace {

template<typename T>
constexpr auto f(T && t) noexcept {
    return true;
}

template<typename T>
constexpr auto f_helper(T && t) noexcept(noexcept(f(t))) {
    return f(t);
}

template<typename T, typename... Ts>
constexpr auto f_helper(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
    return f(ts...);
}

template<typename T, typename... Ts>
constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f_helper(ts...))) {
    return f(ts...);
}

}   // namespace

int main() {
    f(true, 0, 5u);
}

不必定义 f_helper 函数,在这种情况下,它只需具有通过 decltype 指定的正确返回类型。

第一个代码也针对 1 个或 2 个参数进行编译,但是一旦我尝试使用 3 个或更多参数调用它,我就会收到关于没有匹配函数要调用的错误。第一个代码的clang错误是:

source/main.cpp:9:59: error: call to function 'f' that is neither visible in the template definition nor
      found by argument-dependent lookup
        constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
                                                                 ^
source/main.cpp:9:17: note: in instantiation of exception specification for 'f<bool, int, unsigned int>'
      requested here
        constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
                       ^
source/main.cpp:16:3: note: in instantiation of function template specialization '<anonymous
      namespace>::f<bool, int, unsigned int>' requested here
                f(true, 0, 5u);
                ^
source/main.cpp:9:17: note: 'f' should be declared prior to the call site
        constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
                       ^
1 error generated.

【问题讨论】:

  • 如果你将 4 个参数传递给 f,则带有帮助器 doesn't compile 的版本。

标签: c++ c++11 c++14 noexcept


【解决方案1】:

3.3.2/1 名称的声明点紧接在其完整声明符(第 8 条)之后和其初始化程序(如果有)之前...

exception-specification 在语法上是声明符的一部分。因此,函数名称不在其自身异常规范的范围内。

【讨论】:

  • 虽然我在技术上并没有真正递归地调用这个函数,但我调用的是从同一个模板生成的完全不同的函数,它最终调用了单参数函数定义。这对我有帮助吗?
  • 该函数模板的名称不在您尝试使用它的范围内。
  • @DavidStone 我认为可以通过 ADL 找到它?这为黑客打开了大门,您可以在其中使用来自同一 namespace 的虚拟参数创建一个 template 函数实现,并根据所述实现定义面向公众的函数实现。不确定这是否有效。
猜你喜欢
  • 2021-11-03
  • 2017-07-04
  • 1970-01-01
  • 2017-02-08
  • 2020-07-09
  • 2015-10-04
  • 2019-03-29
  • 1970-01-01
相关资源
最近更新 更多