What's the intention behind such kind of template partial specialization?

87 Views Asked by At

when I tried to reconstruct the SGI STL source code, I saw this code snippet

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();
  }
};

which was used to check the validity of the type of the relevant function signatures.

Here is my question: Why SGI intentionally specialized the case of void as return type ?

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;
}

My test code could normally pass the compiling (clang/llvm/x86_64), and normally run.

If I made mistake on either understanding the original code snipped or on the design of my test case, feel free to point it out!

Big thx.

Problem Solved, but FOLLOW UP: why my test case can handle the case of return void type?

1

There are 1 best solutions below

4
On

Even though returning a void expression from a void-returning function is legal C++ since ISO 981, we can imagine some early C++ compilers had not that feature implemented.

On such compiler, the generic template would cause an error for _Ret = void:

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

This is why we can guess a specialization was added (STL is old):

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

1)

[stmt.return]/3

A return statement with an expression of type "cv-void" can be used only in functions with a return type-of-cv-void; the expression is evaluated just before the function returns to its caller.

source (p.98)