0

Is is possible to get a value in a constexpr environment for any type in a generic way, even if the type is not default constructible? If not, why?

As an example, i want to get the index of a type in a std::variant in a constexpr function.

Forgive my misuse of std::is_default_constructible (i used it as a generic, default constructible typeholder), but the name somehow still fits :D

#include <utility>
#include <type_traits>
#include <variant>

//how i made it work without default constructible types..
template <typename T, typename Variant>
constexpr auto index_ugly() {
return [&]<size_t... I>(std::index_sequence<I...>) {
    return std::variant<std::is_default_constructible<
        std::variant_alternative_t<I, Variant>>...>{
        std::is_default_constructible<T>{}}
        .index();
}(std::make_index_sequence<std::variant_size_v<Variant>>{});
}


//how it could look like if i could generate a value
//for the type T regardless of its default constructibility
template<typename T, typename Variant>
constexpr auto index() {
    return Variant{T{}}.index();
}

struct X {
    X (int) {}
};

constexpr int a = index<X, std::variant<int, double, X>>();
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
nnolte
  • 1,628
  • 11
  • 25
  • the example is just an example for a possible use case, i was more interested in why this isn't possible, because it doesn't seem to be – nnolte Feb 07 '19 at 16:11
  • It doesn't have to be default-constructible specifically, that's just the simplest case. It's just that, to construct a value, you need to know how to construct it, and that's not possible in a completely generic way if you put no constraints on the types you handle. – Quentin Feb 07 '19 at 16:13
  • For some cases, [`std::declval`](https://en.cppreference.com/w/cpp/utility/declval) might be useful. Not for your example though. – tkausl Feb 07 '19 at 16:14
  • @Quentin i see, but the question here is why? There is no constructor that will change the type, right? So technically i would want to have something like "just construct this with whatever you want, idc and it changes nothing anyway" – nnolte Feb 07 '19 at 16:17
  • @kawillzocken There actually kind of is. With class template argument deduction `vector(1)` is an `vector` and `vector(1.0)` is a `vector`. These are distinct types so in that cases what is used does change what type you get. – NathanOliver Feb 07 '19 at 16:19
  • @kawillzocken if all you need is the type, then you're already set. If you need an *object* of that type, how you construct it and the resulting value it has is definitely relevant. If you're in a non-evaluated context and you just need a "phantom" value (e.g. for overload resolution inside `decltype`), use `std::declval`. – Quentin Feb 07 '19 at 16:22
  • @NathanOliver If you already know the template instantiation, as it would be the case if you call `index` with `std::vector` or `std::vector`, this does not happen. – Holt Feb 07 '19 at 16:23
  • @NathanOliver i did not think of this, but totally right. thanks^^ – nnolte Feb 07 '19 at 16:23
  • so is the conclusion that i cannot get a "phantom value" in `index` as @Quentin calls it? – nnolte Feb 07 '19 at 16:25
  • I'm closing this as a dupe - since right now it's literally asking that question. But if that's not really the question you have in mind, feel free to edit it to ask something else. – Barry Feb 07 '19 at 16:26
  • @Holt Sure, in this case. I was just speaking generally. like this exmaple: http://coliru.stacked-crooked.com/a/27507c590a89ec81 – NathanOliver Feb 07 '19 at 16:33

0 Answers0