Why the type traits template __or_<_B1, _B2, _B3, _Bn...> needs _B3?

Viewed 59

I'm reading some code in the std c++ type_traits header (in /opt/rh/devtoolset-8/root/usr/include/c++/8/type_traits)

 112   template<typename _B1, typename _B2, typename _B3, typename... _Bn>
 113     struct __or_<_B1, _B2, _B3, _Bn...>
 114     : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type
 115     { };

And I don't understand why we need _B3, because I think B1, B2 and Bn is enough

 001   template<typename _B1, typename _B2, typename... _Bn>
 002     struct __or_<_B1, _B2, _Bn...>
 003     : public conditional<_B1::value, _B1, __or_<_B2, _Bn...>>::type
 004     { };

What's the purpose of _B3 here in the STL _or template?

1 Answers

We are able to look at the source of gcc/libstdc++ and use their VCS to see when __or_ was added. It was added with 123c516a, and looked like:

(direct link)

  template<typename, typename, typename...>
    struct __or_;

  template<typename _B1, typename _B2>
    struct __or_<_B1, _B2>
    : public conditional<_B1::value, _B1, _B2>::type
    { };

  template<typename _B1, typename _B2, typename _B3, typename... _Bn>
    struct __or_<_B1, _B2, _B3, _Bn...>
    : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type
    { };

So originally __or_ only accepted 2 or more arguments and could not be implemented without _B3 (Since _Bn could be an empty parameter pack, and __or_<_B2, _Bn...> would lead to __or_<_B2> being used).

Even after __or_<> : false_type and __or_<T> : T was added, it might still make sense to have the "extra" overload for exactly two arguments, as that's one less template for the compiler to expand. Either way, not much reason to remove it.

Related