0

This code is from C++ STL v3.3 concept_checks.h, 293-300:

template <class _Func, class _Arg>
struct _STL_UNARY_FUNCTION_ERROR<_Func, void, _Arg> {
  static void
  __unary_function_requirement_violation(_Func& __f,
                                      const _Arg& __arg) {
    __f(__arg);
  }
};

Does C++ allow a template to be defined like "struct structname<..>"?

In the above example, what is the use of "<_Func, void, _Arg>"?

If we delete "<_Func, void, _Arg>", does it affect anything?

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • If the code comes from C++ STL v3.3 it obviously must have the grammar. This a template specialisation. – ckruczek Jul 20 '17 at 08:55
  • 2
    Possible duplicate of [C++ templates specialization syntax](https://stackoverflow.com/questions/8323530/c-templates-specialization-syntax) – Dan Jul 20 '17 at 08:55
  • Sorry, I mean [this one](https://stackoverflow.com/questions/3914642/difference-between-instantiation-and-specialization-in-c-templates?noredirect=1&lq=1) but now I can't change it. – Dan Jul 20 '17 at 08:59
  • @Dan - I've seen all of those. None seemed quite right. And I couldn't find a close enough dupe, to my amazement. So I think this one is now the canonical form for when someone asks about this "strage syntax". – StoryTeller - Unslander Monica Jul 20 '17 at 09:00

2 Answers2

0

Does C++ allow a template to be defined like "struct structname<..>"?

Yes, C++ has this syntax. It's defining a partial template specialization. So there is a primary _STL_UNARY_FUNCTION_ERROR template, that is defined somewhat like this:

template <class _Func, typename _Type, class _Arg>
struct _STL_UNARY_FUNCTION_ERROR {
  // ...
};

And the one you quoted gives a specialized version of it. When _Type is void, the resulting class will be defined (according to the remaining two parameters) as the one you have in your question.

In the above example, what is the use of "<_Func, void, _Arg>"?

It specifies the arguments which will make this specialization be chosen when the template is instantiated. So whenever the second type is void, this is how the class will look.

If we delete "<_Func, void, _Arg>", does it affect anything?

Yes. This will make the above a redefinition of the template. And the compiler is required to reject it. The effect is that your program is now ill-formed.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
0

This is a template (partial) specialisation. It changes how the template behaves when the middle template parameter is void

Somewhere above this there will be a declaration like

template <class _Func, class _Ret, class _Arg>
struct _STL_UNARY_FUNCTION_ERROR {
    static _Ret 
    __unary_function_requirement_violation(_Func& __f,
                                      const _Arg& __arg) {
    return __f(__arg);
  }
};

If you remove the <_Func, void, _Arg> you instead have a separate template, with the same name as a previous template, and your program is ill-formed.

Note that were _STL_UNARY_FUNCTION_ERROR<_Func, void, _Arg> to use the main definition, your program would be ill-formed, as you cannot have an expression in the return of a void function.

Caleth
  • 52,200
  • 2
  • 44
  • 75