Clang does not allow static_cast to the parent class with the template, while g ++ and icc allow

I am trying to use my C ++ 11 code to see if the entire last main compiler supports the functions used, and the following abbreviated code

#include <valarray> struct T { double vv[3]; }; class V : public std::valarray<T> { public: auto begin()->decltype(std::begin(static_cast<std::valarray<T>>(*this))) { return std::begin(static_cast<std::valarray<T>>(*this)); } }; int main(void) { } 

will compile with g ++ 4.8.1 (from the Debian sid repository), Intel C ++ 13.1.1 20130313 compiler, but not Clang 3.3-2 (from the sid sid repository).

This error:

 test.cpp:11:73: error: no viable conversion from 'V' to 'std::valarray<T>' auto begin()->decltype(std::begin(static_cast<std::valarray<T>>(*this))) ^~~~~ 

However, such a code

 namespace std { auto begin(V& vv) -> decltype(std::begin(static_cast<V::parent_t>(vv))) { return std::begin(static_cast<V::parent_t>(vv)); } } 

will be compiled by all three compilers.

My question is: is the code itself allowed by the language standard, is it just that Klang compiled it incorrectly or only supports the g ++ / icc extension? Or is this behavior undefined?

+4
source share
1 answer

The code is very dangerous and should be fixed even for GCC and ICC.

You are using static_cast for the type of value, not for reference or pointer. This creates a new temporary valarray object, so a const overload of begin is called (probably not what you intended), and the iterator returned by begin() refers to a temporary one that goes out of scope immediately, so the returned iterator is invalid and dereferences it undefined behavior.

The code will be compiled as follows:

  auto begin()->decltype(std::begin(std::declval<std::valarray<T>&>())) { return std::begin(static_cast<std::valarray<T>&>(*this)); /* cast to reference type! ^^^^^^^^^^^^^^^^^ */ } 

decltype does not need to allocate this , it just needs to know the type of the call std::begin on valarray<T> , so it does not matter if the type is incomplete, because you do not know t needs a listing.

In the body of the function, the type is considered complete in any case, therefore the cast is valid.

0
source

Source: https://habr.com/ru/post/1488184/


All Articles