1

当我试图重构 SGI STL 源代码时,我看到了这段代码片段

template <class _Func, class _Ret>
struct _STL_GENERATOR_ERROR {
  static _Ret __generator_requirement_violation(_Func& __f) {
    return __f();
  }
};
template <class _Func>
struct _STL_GENERATOR_ERROR<_Func, void> {
  static void __generator_requirement_violation(_Func& __f) {
    return __f();
  }
};

用于检查相关函数签名类型的有效性。

这是我的问题:为什么 SGI 故意将 void 的情况专门化为返回类型?

template <class _Func, class _Ret>
struct _STL_GENERATOR_ERROR {
  static _Ret __generator_requirement_violation (_Func& __f) {
    return __f();
  }
};

void hello() {}

int main(int argc, char const *argv[])
{
  void (*ptr)() = &hello;
  _STL_GENERATOR_ERROR<void(*)(), void>::__generator_requirement_violation(ptr);
  return 0;
}

我的测试代码可以正常通过编译(clang/llvm/x86_64),并正常运行。

如果我在理解原始代码或测试用例设计上犯了错误,请随时指出!

非常感谢。

问题已解决,但跟进:为什么我的测试用例可以处理返回 void 类型的情况?

4

1 回答 1

2

尽管从返回 void 的函数返回 void 表达式是合法的 C++,因为 ISO 98 1,我们可以想象一些早期的 C++ 编译器没有实现该功能。

_Ret在这样的编译器上,通用模板会导致=错误void

template <class _Func, class _Ret>
struct _STL_GENERATOR_ERROR {
  static _Ret __generator_requirement_violation(_Func& __f) {
    return __f();
  }
};

这就是为什么我们可以猜测添加了一个专业化(STL 是旧的):

template <class _Func>
struct _STL_GENERATOR_ERROR<_Func, void> {
  static void __generator_requirement_violation(_Func& __f) {
    __f();
  }
};

1)

[stmt.return]/3

带有"cv-void"类型表达式的 return 语句只能在返回类型为 cv-void 的函数中使用;表达式在函数返回其调用者之前被评估。

来源(第 98 页)

于 2020-10-14T14:12:53.287 回答