1

I am trying to simulate the std::visit function in c++17 (gcc7.1)

template<typename ... Ts>
void myvisit(variant<Ts...> v)
{

    size_t N = std::variant_size<decltype(v)>::value;
    for (int i=0;i<N;++i) //try to iterate variadic pack
    {
        using T = decltype(get<i>(v));
        if (holds_alternative<T>(v))
        {
            cout<< get<T>(v);
            break;
        }
    }
}

int main()
{
    using VAR = variant<int, string, double>;
    vector<VAR> vv;
    vv.push_back("app");
    vv.push_back(123);
    vv.push_back(1.02);
    for(auto v:vv)
        myvisit(v);

    return 0;
}

Here I get an issue that:

error: the value of ‘i’ is not usable in a constant expression
using T = decltype(get < i >(v));

I am wondering how to solve it?

camino
  • 10,085
  • 20
  • 64
  • 115
  • 1
    This is where you meet [`std::integer_sequence` and friends](http://en.cppreference.com/w/cpp/utility/integer_sequence). :-] – ildjarn May 09 '17 at 20:26
  • 2
    Why would you implement `std::visit` in this fashion? – Nicol Bolas May 09 '17 at 20:27
  • @NicolBolas just to get familiar with c++17 feature :) – camino May 09 '17 at 20:37
  • @ildjarn Thanks! I will look into it. – camino May 09 '17 at 20:38
  • @camino: I didn't ask why you would implement `visit`. I asked why you would implement it *in this fashion*, with a loop. It's like implementing array access by doing a `for` loop over the array until you get to the given index. – Nicol Bolas May 09 '17 at 20:39
  • @NicolBolas is there any better way to do that? I only can figure out this method. Any suggestions? – camino May 09 '17 at 20:41
  • Not exactly what you asked but... what about as follows? `template void myvisit (variant v) { using unused = int[]; unused { 0, ((holds_alternative(v) ? (std::cout << get(v), 0) : 0), 0)... }; }` – max66 May 09 '17 at 20:45
  • @max66 I got a compile error when calling your function. for example: variant v; v=123; myvisit(v); – camino May 09 '17 at 21:10
  • sorry: my example compile but I've simulated with very very simplified classes; which kind of error do you get? – max66 May 09 '17 at 21:16
  • @max66, error: no matching function for call to ‘holds_alternative, std::allocator >, int>(std::variant, std::allocator >, int>&)’ (holds_alternative(v) ? (std::cout << get(v), 0) : 0) – camino May 09 '17 at 21:18
  • sorry: transcription error (that I've corrected immediatly): is `holds_alternative(v)`, not `holds_alternative(v)`; I also suggest to add `(void)` before the second `unused` (to avoid some warnings). – max66 May 09 '17 at 21:23
  • 1
    The full (I hope correct) example: `template void myvisit (variant v) { using unused = int[]; (void)unused { 0, ((holds_alternative(v) ? (std::cout << get(v), 0) : 0), 0)... };}` – max66 May 09 '17 at 21:25
  • @max66 It works now. That 's awesome solution! Thanks so much!! – camino May 09 '17 at 21:26
  • @camino : Except that you very likely want `v.index()`, _not_ `holds_alternative(v)`... ;-] The latter simply returns whether a type is unique in the list of alternatives, not whether it is the active variant alternative. – ildjarn May 09 '17 at 22:02
  • @ildjarn I change it to void myvisit( ..... ){std::cout << get(v)<, std::allocator >, double>::index()>(std::variant, std::allocator >, double>&)’ – camino May 11 '17 at 20:59
  • @camino : `variant::index()` isn't constexpr and so isn't usable directly in that way. If it were that easy they wouldn't bother including the complex `std::visit`... ;-] – ildjarn May 11 '17 at 23:42
  • @ildjarn I checked cppreference.com, it shows that constexpr std::size_t index() const noexcept , – camino May 12 '17 at 00:48
  • @camino : I meant in _this_ context, since `v` is not constexpr object. :-] – ildjarn May 12 '17 at 03:15
  • @ildjarn I see, Thanks a lot, anyway – camino May 12 '17 at 13:05
  • my question is answered in this post https://stackoverflow.com/questions/37602057/why-isnt-a-for-loop-a-compile-time-expression/37602149#37602149 – camino May 22 '17 at 18:18

0 Answers0