How to get around Intel C ++ compiler issue with `decltype` and inheritance?

Today I was very surprised to find that Intel icpc (version 14.0.2 using std=c++0x ) could not compile the following snippet.


 #include <type_traits> namespace traits_tests { template<typename> struct sfinae_true : std::true_type {}; template<typename T> static auto value_type(int) -> sfinae_true<typename T::value_type>; template<typename T> static auto value_type(void*) -> std::false_type; } template<typename C> struct has_value_type : decltype(traits_tests::value_type<C>(0)) {}; 

complains about the last line:

 inc/traits.h(258): error: expected an identifier : decltype(traits_tests::value_type<C>(0)) {}; ^ 

The code works fine with clang and gcc .

I really do not like the complete rewrite to make it work with erroneous compilers (why are commercial compilers erroneous?).

  • Is there an easier way than a completely different SFINAE template to make it work with icc ?

EDIT : Yes, I know icc supporting decltype since some time. But in the specific context above, icc does not support it. Also note that using std=c++11 instead of std=c++0x does not matter.

+6
source share
2 answers

You can use a template-based workaround β€” any of the standard types that take an argument of the type of the template and display it as typedef , and then transfer it to a macro that is specific to ICC only, for example.

 #ifdef __INTEL_COMPILER #include <utility> #define decltype(...) \ std::pair<decltype(__VA_ARGS__), int>::first_type #endif 

Allows you to compile your example without modification.

Once the error has been fixed in all versions of ICC that you use, you can remove the macro definition without changing any other code.

(see this answer for a similar problem with MSVC)

+3
source

As pointed out in the question and comments, decltype maintained in icc for some time; the problem is that it cannot be used in every context due to an unpleasant compiler error.


More specifically, it cannot be used directly when specifying the class base, which requires us to write a workaround.

If we cannot use it directly, use it indirectly (via the alias template)!


EXAMPLE OF WORK

 template<class T> using identity_hack = T; template<typename C> struct has_value_type : identity_hack<decltype (traits_tests::value_type<C> (0))> { } 

Note. There are many variations of the above, for example, you can use std::enable_if<true, decltype (...)>::type as an alternative if you do not want to declare something of your own.

+4
source

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


All Articles