Информация об изменениях

Сообщение Re: std::is_constant_evaluated() от 18.04.2020 11:31

Изменено 18.04.2020 11:33 Vain

Re: std::is_constant_evaluated()
Здравствуйте, Videoman, Вы писали:

V>P.S. Желательно под MSVS 2017, v.141

Да будут же жить макросы вечно! (спасибо последнему стандарту)
  https://godbolt.org/z/fWMFKV
#include <type_traits>
#include <cstdio>

#define UTILITY_CONSTEXPR(exp)                          (::utility::constexpr_bool<(exp) ? true : false>::value)

#ifndef __clang__
#define UTILITY_IS_CONSTEXPR_VALUE(...)                 UTILITY_CONSTEXPR(noexcept(::utility::makeprval((__VA_ARGS__, 0))))
#else
#define UTILITY_IS_CONSTEXPR_VALUE(...)                 UTILITY_CONSTEXPR(__builtin_constant_p((__VA_ARGS__, 0)))   // can be used for the GCC too
#endif

namespace utility
{
    // to suppress `warning C4127: conditional expression is constant`
    template <bool B, typename...>
    struct constexpr_bool
    {
        static constexpr const bool value = B;
    };

    template <bool B, typename... types>
    const bool constexpr_bool<B, types...>::value;

    // remove_reference + remove_cv
    template <typename T>
    struct remove_cvref
    {
        using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
    };

    // CAUTION:
    //  Return values in the `makeprval` are required to avoid breakage in the `Visual Studio 2015 Update 3` compiler.
    //
    template <typename T>
    constexpr typename remove_cvref<T>::type makeprval(T && v)
    {
        return v;
    }

    // static array type must be overloaded separately, otherwise will be an error: `error: function returning an array`
    template <typename T>
    constexpr const typename remove_cvref<T>::type & makeprval(const T & v)
    {
        return v;
    }
}

inline int myintrinsic_add(int a, int b)
{
    return a + b + 1;
}

template <bool is_constexpr>
struct t_optimized_add
{
    constexpr int operator()(int a, int b) const
    {
        return a + b;
    }
};

template <>
struct t_optimized_add<false>
{
    int operator()(int a, int b) const
    {
        return myintrinsic_add(a, b);
    }
};

#define OPTIMIZED_ADD(a, b)     t_optimized_add<UTILITY_IS_CONSTEXPR_VALUE(t_optimized_add<true>()(a, b))>()(a, b)

static int a = 100;

int main()
{
    printf("%d\n", OPTIMIZED_ADD(1, 1));
    printf("%d\n", OPTIMIZED_ADD(a, 1));
}
Re: std::is_constant_evaluated()
Здравствуйте, Videoman, Вы писали:

V>P.S. Желательно под MSVS 2017, v.141

Да будут же жить макросы вечно! (спасибо последнему стандарту)
  https://godbolt.org/z/fWMFKV
#include <type_traits>
#include <cstdio>

#define UTILITY_CONSTEXPR(exp)                          (::utility::constexpr_bool<(exp) ? true : false>::value)

#ifndef __clang__
#define UTILITY_IS_CONSTEXPR_VALUE(...)                 UTILITY_CONSTEXPR(noexcept(::utility::makeprval((__VA_ARGS__, 0))))
#else
#define UTILITY_IS_CONSTEXPR_VALUE(...)                 UTILITY_CONSTEXPR(__builtin_constant_p((__VA_ARGS__, 0)))   // can be used for the GCC too
#endif

namespace utility
{
    // to suppress `warning C4127: conditional expression is constant`
    template <bool B, typename...>
    struct constexpr_bool
    {
        static constexpr const bool value = B;
    };

    template <bool B, typename... types>
    const bool constexpr_bool<B, types...>::value;

    // remove_reference + remove_cv
    template <typename T>
    struct remove_cvref
    {
        using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
    };

    // CAUTION:
    //  Return values in the `makeprval` are required to avoid breakage in the `Visual Studio 2015 Update 3` compiler.
    //
    template <typename T>
    constexpr typename remove_cvref<T>::type makeprval(T && v)
    {
        return v;
    }

    // static array type must be overloaded separately, otherwise will be an error: `error: function returning an array`
    template <typename T>
    constexpr const typename remove_cvref<T>::type & makeprval(const T & v)
    {
        return v;
    }
}

inline int myintrinsic_add(int a, int b)
{
    return a + b + 1;
}

template <bool is_constexpr>
struct t_optimized_add
{
    constexpr int operator()(int a, int b) const
    {
        return a + b;
    }
};

template <>
struct t_optimized_add<false>
{
    int operator()(int a, int b) const
    {
        return myintrinsic_add(a, b);
    }
};

#define OPTIMIZED_ADD(a, b) \
    t_optimized_add<UTILITY_IS_CONSTEXPR_VALUE(t_optimized_add<true>()(a, b))>()(a, b)

static int a = 100;

int main()
{
    printf("%d\n", OPTIMIZED_ADD(1, 1));
    printf("%d\n", OPTIMIZED_ADD(a, 1));
}