# Compiler workarounds

This page tracks the workarounds for the various compiler issues that we encountered in the development. This is mostly of interest for developers interested in contributing to xtensor.

## Visual Studio 2015 and `std::enable_if`

With Visual Studio, `std::enable_if` evaluates its second argument, even if the condition is false. This is the reason for the presence of the indirection in the implementation of the `xfunction_type_t` meta-function.

## GCC-4.9 and Clang < 3.8 and constexpr `std::min` and `std::max`

`std::min` and `std::max` are not constexpr in these compilers. In `xio.hpp`, we locally define a `XTENSOR_MIN` macro used instead of `std::min`. The macro is undefined right after it is used.

## Clang < 3.8 matching `initializer_list` with static arrays

Old versions of Clang don’t handle overload resolution with braced initializer lists correctly: braced initializer lists are not properly matched to static arrays. This prevent compile-time detection of the length of a braced initializer list.

A consequence is that we need to use stack-allocated shape types in these cases. Workarounds for this compiler bug arise in various files of the code base. Everywhere, the handling of Clang < 3.8 is wrapped with checks for the `X_OLD_CLANG` macro.

## GCC < 5.1 and `std::is_trivially_default_constructible`

The version of libstdc++ shipped with GCC older than 5.1 (and also used by Clang on linux) does not implement `std::is_trivially_default_constructible` but `std::has_trivial_default_constructor` instead. With GCC, this is done with a simple check of the version of GCC. In the case of the clang - linux combination, libstdc++ may be used. Since clang overrides the `__GNUC__` macro, the version of libstdc++ used cannot be retrived at runtime and some meta-programming techniques are used to determine which function is available.

## GCC-6 and the signature of `std::isnan` and `std::isinf`

We are not directly using `std::isnan` or `std::isinf` for the implementation of `xt::isnan` and `xt::isinf`, as a workaround to the following bug in GCC-6 for the following reason.

- C++11 requires that the `<cmath>` header declares `bool std::isnan(double)` and `bool std::isinf(double)`.
- C99 requires that the `<math.h>` header declares `int ::isnan(double)` and `int ::isinf(double)`.

These two definitions would clash when importing both headers and using namespace std.

As of version 6, GCC detects whether the obsolete functions are present in the C `<math.h>` header and uses them if they are, avoiding the clash. However, this means that the function might return int instead of bool as C++11 requires, which is a bug.