I was very surprised today to discover that Intel's icpc (version 14.0.2, using std=c++0x
) fails to 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)) {};
complaining 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 don't really fancy a complete re-write to make it work with flawed compilers (why is that always the commercial compilers are flawed?).
icc
?EDIT: Yes, I know that icc
supports decltype
since some time. But in the particular context above, icc
fails to support it. Also note that using std=c++11
instead of std=c++0x
makes no difference.
As stated in the question, and comments, decltype
has been supported in icc
for some time now; the problem is that it's not usable in every context because of a nasty bug in the compiler.
More specifically it cannot be used directly when specifying the base of a class, which requires us to write a workaround..
If we can't use it directly, let's use it indirectly (through an alias template)!
EXAMPLE WORKAROUND
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 to the above, one could for example use std::enable_if<true, decltype (...)>::type
as an alternative if one doesn't want to declare something of their own.
You can use a template based workaround - any of the standard types that take a template type argument and expose it as a typedef
, then wrap that in a macro that's only defined for ICC e.g.
#ifdef __INTEL_COMPILER
#include <utility>
#define decltype(...) \
std::pair<decltype(__VA_ARGS__), int>::first_type
#endif
Which allows your example to compile without changes.
Once the bug is fixed in all versions of ICC you're using you can remove the macro definition without changing any other code.
(See this answer to a similar MSVC issue)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With