The following code below works fine in clang or gcc, but fails with intel compiler 2016.
Note if you comment out the section of code labeled block A (which has nothing to do with anything and isn't referenced) the code compiles. It seems that somehow it's corrupting icc. Please suggest a work around and let me know when you have a patch available.
#include <type_traits>
template <bool... Values>
struct And {
static constexpr bool value = true;
};
template <bool ValueFirst, bool... ValuesRest>
struct And<ValueFirst, ValuesRest...> {
static constexpr bool value = ValueFirst && And<ValuesRest...>::value;
};
class Concept {
protected:
// list
template <bool... Values>
using list = std::integral_constant<bool, And<Values...>::value>;
// valid
template <class T>
static constexpr bool valid() {
return true;
}
// same
template <class A, class B>
static constexpr bool same() {
return std::is_same<A, B>();
}
// convertible
template <class A, class B>
static constexpr bool convertible() {
return std::is_convertible<A, B>();
}
};
namespace detail {
namespace concept {
template <
class Concept, class... Args,
typename T = decltype(std::declval<Concept>().template require<Args...>(
std::declval<Args>()...)),
typename std::enable_if<std::is_same<T, std::true_type>::value, int>::type =
0>
std::true_type models_(Args&&... args);
template <class Concept, class... Args>
std::false_type models_(...);
} // end namespace concept
} // end namespace detail
template <class Concept, class... Args>
constexpr bool models() {
using Result = decltype(
detail::concept::models_<Concept, Args...>(std::declval<Args>()...));
return Result{};
}
struct Scalar : Concept {
template <class T>
auto require(T&& x)
-> list<std::is_pod<T>::value, same<T, decltype(-x)>(),
same<T, decltype(x + x)>(), same<T, decltype(x - x)>(),
same<T, decltype(x* x)>(), same<T, decltype(x / x)>()>;
};
template <class T>
constexpr bool scalar() {
return models<Scalar, T>();
}
/************* Block A ***********/
struct MatrixEvaluator : Concept {
template <class T>
auto require(T&& evaluator)
-> list<scalar<std::decay_t<decltype(evaluator(0, 0, 0, 0))>>()>;
};
/************* End Block A ***********/
struct VectorEvaluator : Concept {
template <class T>
auto require(T&& evaluator)
-> list<scalar<std::decay_t<decltype(evaluator(0))>>()>;
};
template <class T>
constexpr bool vector_evaluator() {
return models<VectorEvaluator, T>();
}
int main() {
auto f = [](int x) -> double { return x * x; };
static_assert(vector_evaluator<decltype(f)>(), "");
return 0;
}