I have the following template / compile-time utility helper functions. It works fine in all three compilers (MSVC, GCC, clang) when everything is constexpr, but changing a few bits to consteval results in an odd error in MSVC. I want to migrate all my constexpr machinery to consteval as much as possible, and this problem is not helping.
#include <optional> #include <tuple> #include <type_traits> template <auto v> struct value_as_type { static constexpr auto value = v; using type = decltype(value); consteval operator type() const noexcept { return v; } }; template <size_t First, size_t Last, typename Functor> consteval void consteval_for([[maybe_unused]] Functor&& f) noexcept { if constexpr (First < Last) { if constexpr (std::is_same_v<bool, std::invoke_result_t<Functor()>>) { if (f(value_as_type<First>{}) == false) return; } else f(value_as_type<First>{}); consteval_for<First + 1, Last>(std::forward<Functor>(f)); } } template <size_t index, typename... Args> using type_by_index = std::tuple_element_t<index, std::tuple<Args...>>; template <typename T, typename... Args> [[nodiscard]] consteval std::optional<size_t> index_for_type() noexcept { std::optional<size_t> index; consteval_for<0, sizeof...(Args)>([&index](auto i) { if (!index) // The index of the first occurrence is stored { if constexpr (std::is_same_v<T, type_by_index<static_cast<size_t>(i), Args... >> ) index = static_cast<size_t>(i); } }); return index; } static_assert(index_for_type<int, float, void, int, bool>() == 2); The error message is:
<source>(52): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'std::optional<size_t>' <source>(52): note: Invalid aggregate initialization I'm not seeing any aggregate initialization of the optional at all. And my question is: do you think it's a bug in MSVC, or is there something not right with my code?
P. S. Removing optional and just returning size_t removes the error, but I do need a way to say "the type is not present in the pack" without compilation error. std::optional seems the perfect fit for this semantically.
static_assert. Not helpful at all.value_as_type,consteval_for,type_by_index) separately using static_assert?value_as_typedoesn't seem necessary or useful. Does it work if that layer is eliminated?value_as_typein favor ofstd::integral_constant