[Dune-devel] PSA: please avoid implicit conversion integral_constant<bool, ...> to bool

Steffen Müthing steffen.muething at iwr.uni-heidelberg.de
Mon Feb 20 16:28:04 CET 2017


> Am 20.02.2017 um 13:10 schrieb Jö Fahlke <jorrit at jorrit.de>:
> 
> Hi!
> 
> I've seen expression like `std::is_same<T1, T2>()` (or any other type
> predicate) where the result is implicitly converted to `bool` pop up
> throughout Dune for some time now.  Please stop that; they can't work in all
> cases, and when they break they lead to hard-to-diagnose errors.
> 
> I recommend picking whatever appears least ugly to you from the following
> list, and to use it whenever you need the value of an `integral_constant`.
> 
> - `std::is_same<T1, T2>::value`
> 
> - `std::is_same<T1, T2>().value` or `std::is_same<T1, T2>{}.value`
> 
> - `std::is_same<T1, T2>()()` or `std::is_same<T1, T2>{}()`
> 
> - `(bool)std::is_same<T1, T2>()` or `(bool)std::is_same<T1, T2>{}` or other
>  explicit casts
> 
> At the very least, please use it whenever you deal with `integral_constant`
> results of type predicates or type property queries.
> 
> Rationale
> =========
> 
> Trick Question
> --------------
> 
> In the following program, will the `static_assert()` trigger, or will the
> program compile?
> 
> ```c++
> #include <tuple>
> #include <type_traits>
> 
> int main() {
>  static_assert(!std::is_same<std::tuple<void>, int>(), "Strange...");
> }

That’s an interesting issue - it’s fine as long as you guarantee that the bool conversion
happens before anything else, because any kind of logical operation on the type will
trigger ADL. That said, using std::tuple<void> is an **interesting** choice of marker
type ;-)

BTW: The committee has recognized this problem as well, and starting with C++17
you can just write

std::is_same_v<T,U>

which is a constexpr variable template defined approximately like this:

template<typename T, U>
constexpr bool is_same_v = is_same<T,U>::value;

Steffen

> 
> ```
> 
> Spoiler
> -------
> 
> You will get an error similar to the following:
> ```
> g++ -Wall -std=c++14 -o test test.cc
> In file included from test.cc:1:0:
> /usr/include/c++/4.9/tuple: In instantiation of ‘struct std::_Head_base<0ul, void, false>’:
> /usr/include/c++/4.9/tuple:231:12:   required from ‘struct std::_Tuple_impl<0ul, void>’
> /usr/include/c++/4.9/tuple:390:11:   required from ‘class std::tuple<void>’
> test.cc:5:54:   required from here
> /usr/include/c++/4.9/tuple:134:17: error: forming reference to void
>       constexpr _Head_base(const _Head& __h)
>                 ^
> ```
> 
> Explanation
> -----------
> 
> `std::is_same` is a proper class template, not a typedef template, so `!` will
> use ADL to find candidate functions implementing it.  The set of namespaces
> for ADL includes the set of namespaces associated with `std::tuple<void>`,
> which in turn includes the set of namespaces associated with any base classes
> of `std::tuple<void>`.  To determine the base classes, `std::tuple<void>` must
> be completed, but you can't have a complete class with a `void` data member or
> (which triggers the error here) a constructor taking a `const void &`
> parameter.
> 
> Occurance
> ---------
> 
> I last came across this when writing a unit test for `Dune::TypeList` and
> associated utilites.  `Dune::IsEmptyTypeList<T>` is a type predicate that is
> supposed to tell you for any type `T` whether it is and empty typelist.
> Except that if `T` is a class type, it needlessly tries to complete it, so
> ```
> static_assert(!Dune::IsEmptyTypeList<std::tuple<void> >::value, "...");
> ```
> does not work as intended.  Even though I use `::value` here, because
> `IsEmptyTypeList` uses the implicit conversion to `bool` internally.
> 
> 
> Regards,
> Jö.
> 
> --
> _______________________________________________
> Dune-devel mailing list
> Dune-devel at dune-project.org
> http://lists.dune-project.org/mailman/listinfo/dune-devel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <https://lists.dune-project.org/pipermail/dune-devel/attachments/20170220/9ff8b497/attachment.sig>


More information about the Dune-devel mailing list