PVRT
PVRT

Reputation: 520

Variadic template with explicit arguments and sizeof... Visual Studio 2013

I was trying to enumerate a variadic tuple, so that i can perform certain operations on each of its elements.

#include <iostream>
#include <tuple>
#include <utility>

template <size_t N, typename ...Args>
typename std::enable_if<N == sizeof...(Args), void>::type
print(std::tuple<Args...> const& tuples)
{ }

template <size_t N, typename ...Args>
typename std::enable_if<(N < sizeof...(Args)), void>::type
print(std::tuple<Args...> const& tuples)
{
    std::cout << std::get<N>(tuples);
    print<N + 1>(tuples);
}

template <typename ...Args>
void printTuples(std::tuple<Args...> const& tuples)
{
    print<0>(tuples);
}

int main(int argc, char** argv)
{
    printTuples(std::make_tuple(1, 2.,3.));
    return 0;
}

In visual studio 2013 this results in following error:

1>main.cpp(15): error C2770: invalid explicit template argument(s) for 'std::enable_if<N<1,void>::type print(std::tuple<_Types1...> &)'
1>main.cpp(15): error C2893: Failed to specialize function template 'std::enable_if<N==1,void>::type print(std::tuple<_Types1...> &)'

This compiles fine in VS2015. Could anyone please explain me why sizeof...(Args) was deduced to 1, even though a tuple with 3 arguments have been passed? Also why is this an error in VS2013 and not on VS2015?

Note: I built a work-around (for VS2013) by enumerating the tuple backwards (starting at the end)

Upvotes: 3

Views: 197

Answers (1)

max66
max66

Reputation: 66230

Could anyone please explain me why sizeof...(Args) was deduced to 1, even though a tuple with 3 arguments have been passed?

I can't.

Maybe a compiler bug?

Or an inadequate C++11 support?

Also why is this an error in VS2013 and not on VS2015?

I don't understand how can VS2015 compile your code because there is an error: your print() and printTuple() functions are receiving a not-const l-value reference but you call printTuple() in main()

printTuples(std::make_tuple(1, 2.,3.));

with a r-value (that is incompatible with a not-const l-value reference).

Suggestion: modify your functions to receive a const l-value reference

template <std::size_t N, typename ...Args>
typename std::enable_if<N == sizeof...(Args)>::type
   print (std::tuple<Args...> const & tuples)
 { } // ......................^^^^^

template <std::size_t N, typename ...Args>
typename std::enable_if<(N < sizeof...(Args))>::type
   print (std::tuple<Args...> const & tuples)
 { // ........................^^^^^
   std::cout << std::get<N>(tuples);
   print<N + 1u>(tuples);
 }

template <typename ...Args>
void printTuples (std::tuple<Args...> const & tuples)
 { print<0u>(tuples); } // ...........^^^^^

Upvotes: 1

Related Questions