I am working on a project where I require saving argument packs (tuples) with different types of values (cannot overload functions since there are too many posibilities). I have reached the code below but receive the error:
Error C1001 An internal error has occurred in the compiler.
tupletest.cpp 47
I have removed optimisations and disabled whole program optimizations (as well as remove the visual studio folders in roaming and local to remove specifications)
Sorry for the long read (a lot of code included)
also tried in the form of:
template<class arg>
std::tuple<arg> GetTuple()
{...}
template<class arg, typename... args>
std::tuple<arg,args...> GetTuple(json::object::iterator it, json::object::iterator end)
{...}
however I receive and error of the sort:
Error C2440 'return': cannot convert from 'std::tuple<std::string,int,int,std::string,std::string>' to 'std::tuple<int,int,int,std::string,std::string>'
template<typename... args, class...refargs>
std::tuple<int, args...> GetTupleFromArgs(std::reference_wrapper<int> refarg, refargs... refargs)
{
return std::tuple_cat(std::make_tuple(refarg.get()), GetTupleFromArgs<args...>(refargs...));
}
std::tuple<int> GetTupleFromArgs(std::reference_wrapper<int> refarg)
{
return std::make_tuple(refarg.get());
}
template<typename... args, class...refargs>
std::tuple<float, args...> GetTupleFromArgs(std::reference_wrapper<float> refarg, refargs... refargs)
{
return std::tuple_cat(std::make_tuple(refarg.get()), GetTupleFromArgs<args...>(refargs...));
}
std::tuple<float> GetTupleFromArgs(std::reference_wrapper<float> refarg)
{
return std::make_tuple(refarg.get());
}
template<typename... args, class...refargs>
std::tuple<std::string, args...> GetTupleFromArgs(std::reference_wrapper<std::string> refarg, refargs... refargs)
{
return std::tuple_cat(std::make_tuple(refarg.get()), GetTupleFromArgs<args...>(refargs...));
}
std::tuple<std::string> GetTupleFromArgs(std::reference_wrapper<std::string> refarg)
{
return std::make_tuple(refarg.get());
}
int main()
{
int a = -1;
int b = 2;
int c = 3;
std::string r = "hel";
std::string v = "he2l";
std::tuple<int, int, int, std::string, std::string> tuple = GetTupleFromArgs(std::ref(a), std::ref(b), std::ref(c), std::ref(r), std::ref(v));
//std::cout << _pack.GetInt<0>();
std::cout << "Hello World!\n";
}
I expected that the values inside the tuple be -1,2,3,"hel","he2l"
, but receive compile time Error C1001 An internal error has occurred in the compiler.
It's a compiler error.
So something unexpected is happened inside the compiler and isn't (completely) your fault.
Anyway, I see that you mix names of types and names of values; by example, in this function
// ................................VVVVVVV
template<typename... args, class...refargs>
std::tuple<int, args...> GetTupleFromArgs(std::reference_wrapper<int> refarg, refargs... refargs)
{ ............................................................................^^^^^^^....^^^^^^^
you named refargs
both the name of the types of the second variadic list and the name of the rispective values.
Bad choice.
Maybe the choice that activate the compiler error.
Same problem with all three recursive version of GetTupleFromArgs()
.
Another problem of the recursive version of GetTupleFromArgs
is that the first variadic list of types can't be deduced because is relative to the return value.
Maybe a little of topic but I propose you to rewrite GetTupleFromArgs()
simply as follows
template <typename ... As>
std::tuple<As...> GetTupleFromArgs (std::reference_wrapper<As> ... rAs)
{ return { rAs.get() ... }; }
This way the single variadic list can be deduced from the argument of the function and there isn't needs of recursion and overloading
Another suggestion: avoid to name tuple
a variable of type std::tuple
. Just to avoid a name collision.
The following is a simplified (and compilable) version of your code
#include <tuple>
#include <iostream>
#include <functional>
#include <type_traits>
template <typename ... As>
std::tuple<As...> GetTupleFromArgs (std::reference_wrapper<As> ... rAs)
{ return { rAs.get() ... }; }
int main ()
{
int a = -1;
int b = 2;
int c = 3;
std::string r = "hel";
std::string v = "he2l";
auto tpe = GetTupleFromArgs(std::ref(a), std::ref(b), std::ref(c),
std::ref(r), std::ref(v));
static_assert( std::is_same<decltype(tpe),
std::tuple<int, int, int, std::string, std::string>
>::value, "!" );
}