Я сделал функцию, которая объединяет несколько меньших значений в одно большее значение, сохраняя при этом двоичное представление значений (например, для построения int argb
из множества unsigned char r, g, b, a
).Я знаю, что я также могу добиться этого путем сдвига битов значений, но это не вопрос этого вопроса.
Однако, если я использую функцию для фактического генерирования целого числа из этих значений, msvc выдает ошибку компилятора:
error C3615: constexpr function 'Color::operator int' cannot result in a constant expression
note: failure was caused by call of undefined function or one not declared 'constexpr'
note: see usage of '<lambda_dcb9c20fcc2050e56c066522a838749d>::operator ()'
Здесь - полный образец.Clang и gcc компилируют код, но msvc отказывается:
#include <type_traits>
#include <memory>
namespace detail
{
template <typename From, typename To, size_t Size>
union binary_fusion_helper
{
const From from[Size];
const To to;
};
template <typename To, typename Arg, typename ...Args, typename = std::enable_if_t<(... && std::is_same_v<std::remove_reference_t<Arg>, std::remove_reference_t<Args>>)>>
constexpr To binary_fusion(Arg arg, Args... args)
{
using in_t = std::remove_reference_t<Arg>;
using out_t = To;
static_assert(sizeof(out_t) == sizeof(in_t) * (sizeof...(Args) + 1), "The target type must be of exact same size as the sum of all argument types.");
constexpr size_t num = sizeof(out_t) / sizeof(in_t);
return binary_fusion_helper<in_t, out_t, num> { std::forward<Arg>(arg), std::forward<Args>(args)... }.to;
}
}
template <typename To>
constexpr auto binary_fusion = [](auto ...values) -> To
{
return detail::binary_fusion<std::remove_reference_t<To>>(values...);
};
struct Color
{
float r, g, b, a;
explicit constexpr operator int() const noexcept
{
return binary_fusion<int>(static_cast<unsigned char>(r * 255), static_cast<unsigned char>(g * 255),
static_cast<unsigned char>(b * 255), static_cast<unsigned char>(a * 255));
}
};
Clang и gcc просто игнорируют, что код никогда не будет работать как constexpr или msvc неверен?И если msvc верен, почему функция не может быть запущена во время компиляции?