Search code examples
c++compiler-errorsvariadic

c++ fatal error C1001 on using variadic template


Hi everybody. Compiling my code I came upon the next error:
fatal error C1001: An internal error has occurred in the compiler.

When I pass only one parameter to "exec" function, everything is ok. But when I pass more then one parameters it issues an error. I use vs 2015 and visual c++ compiler respectively.

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
//using namespace std;

template <class T>
void param_push_(T arg, char ** param) {
  sprintf(*param, "%15.15e", arg);
}

template <class T, class... args>
void param_push_(T first, args... args, char ** param) {
  static int param_No = 0;
  sprintf(param[param_No++], "%15.15e", first);
  param_push(args..., param[param_No]);
}

template <class ... param_types>
void exec(const char * command, const param_types& ...param_values) {

  int arg_count = sizeof...(param_values);
  char ** params = new char*[arg_count];
  for (int i = 0; i < arg_count; ++i) {
    params[i] = new char[22 * sizeof(char)];
  }

  param_push_(param_values..., params); //cast parameters to (char *)  

  for (int i = 0; i < arg_count; ++i) {
    delete[] params[i];
  }
  delete[] params;

}

int main()
{
  double e_restriction = 0.55300000000000000000124124;
  double M_restriction = 5;

  exec("SELECT \"M\",e from orbital WHERE e < $1::double precision AND \"M\" < $2::double precision", e_restriction,M_restriction);

  return 0;
}

Solution

  • Try this - it works.

    #include <stdio.h>
    #include <iostream>
    
    template <typename ...> struct param_push;
    
    template <class H, class... T>
    struct param_push<H,T...> {
       void operator() (H head, T... tail, char** param) {
         sprintf(param[0], "%15.15e", head);
         param_push<T...> one_less;
         one_less(tail..., &param[1]);
       }
    };
    
    template <>
    struct param_push<> {
      void operator() (char** param) {
        // does nothing, no more args to sprintf
      }
    };
    
    template <class ... param_types>
    void exec(const char * command, const param_types& ...param_values) {
    
      int arg_count = sizeof...(param_values);
      char ** params = new char*[arg_count];
      for (int i = 0; i < arg_count; ++i) {
        params[i] = new char[22 * sizeof(char)];
      }
    
      // param_push_(param_values..., params); //cast parameters to (char *)
      struct param_push<param_types...> functor;
      functor(param_values..., params);
    
      for (int i = 0; i < arg_count; ++i) {
        std::cout << params[i] << " will be deleted" << std::endl;
        delete[] params[i];
      }
      delete[] params;
    
    }
    
    int main()
    {
      double e_restriction = 0.55300000000000000000124124;
      double M_restriction = 5;
    
      exec("SELECT \"M\",e from orbital WHERE e < $1::double precision AND \"M\" < $2::double precision", e_restriction,M_restriction);
    
      return 0;
    }
    

    (and now, homework for Arty Zefirov: find the reason why when using template struct functors the technique works, why it fails for templated functions and update your question with the findings)