【问题标题】:c++ fatal error C1001 on using variadic templatec++ 使用可变参数模板时出现致命错误 C1001
【发布时间】:2016-08-29 13:19:39
【问题描述】:

大家好。编译我的代码时遇到了下一个错误:
致命错误 C1001:编译器发生内部错误。

当我只将一个参数传递给“exec”函数时,一切正常。但是当我传递多个参数时,它会发出错误。我分别使用 vs 2015 和 Visual c++ 编译器。

#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;
}

【问题讨论】:

  • “内部错误”意味着这是一个编译器错误,无论您的代码是否有效。在正常情况下,编译器应该要么编译代码,要么打印更合理的错误。
  • 尝试将函数“exec”重命名为其他名称。只是一个猜测。不应该对 MS 造成问题,但谁知道呢。除了看一些 MS 资源,因为它是一个编译器问题。
  • 用 gcc 试过了。在param_push_ 的声明中,尝试为args 使用与其类型不同的名称。例如。 args... args_ 而不是 args... args (并相应地在 3 行之后将调用更改为 param_push)。没有更多的铿锵声
  • 当我用 VS2015 编译它时,我得到:error C2660: 'param_push_': function does not take 3 arguments。只是可以重现它。添加另一个值会导致问题。
  • 我在调用递归时更改了“args”参数的名称和固定的函数名称“param_push”。现在我也得到:error C2660: 'param_push_': function does not take 3 arguments

标签: c++ compiler-errors variadic


【解决方案1】:

试试这个 - 它有效。

#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;
}

(现在,Arty Zefirov 的作业:找出使用模板结构函子时该技术有效的原因,模板化函数失败的原因,并用调查结果更新您的问题)

【讨论】:

    【解决方案2】:

    这是尝试在 gcc 上编译此代码的输出:

    12 : error: declaration of 'args ... args'
    void param_push_(T first, args... args, char ** param) {
    ^
    11 : error: shadows template parm 'class ... args'
    template <class T, class... args>
    ^
    /tmp/gcc-explorer-compiler116729-61-oaaqho/example.cpp: In function 'void param_push_(T, args ..., char**)':
    12 : error: declaration of 'args ... args'
    void param_push_(T first, args... args, char ** param) {
    ^
    11 : error: shadows template parm 'class ... args'
    template <class T, class... args>
    ^
    /tmp/gcc-explorer-compiler116729-61-oaaqho/example.cpp: In instantiation of 'void exec(const char*, const param_types& ...) [with param_types = {double, double}]':
    41 : required from here
    27 : error: no matching function for call to 'param_push_(const double&, const double&, char**&)'
    param_push_(param_values..., params); //cast parameters to (char *)
    ^
    7 : note: candidate: template<class T> void param_push_(T, char**)
    void param_push_(T arg, char ** param) {
    ^
    7 : note: template argument deduction/substitution failed:
    27 : note: cannot convert 'param_values#1' (type 'const double') to type 'char**'
    param_push_(param_values..., params); //cast parameters to (char *)
    ^
    12 : note: candidate: template<class T, class ... args> void param_push_(T, args ..., char**)
    void param_push_(T first, args... args, char ** param) {
    ^
    12 : note: template argument deduction/substitution failed:
    27 : note: cannot convert 'param_values#1' (type 'const double') to type 'char**'
    param_push_(param_values..., params); //cast parameters to (char *)
    ^
    Compilation failed
    

    您可能需要重新考虑一下:

    template <class T, class... Args>
    void param_push_(T first, Args... args, char ** param) {
    
      //
      // WARNING: param_No will be a different variable for each
      // combination of Args...
      //
      static int param_No = 0;
    
      sprintf(param[param_No++], "%15.15e", first);
      param_push(args..., param[param_No]);
    }
    

    【讨论】:

      【解决方案3】:

      这是一个新代码。模板函数不会混淆当前参数。但它应该做,不是吗?

      #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_temp, char ** param) {
        static int param_No = 0;
        sprintf(param[param_No++], "%15.15e", first);
        param_push_(args_temp..., param[param_No]);
      }
      
      template <class ... param_types>
      void my_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;
        param_push_<double, double, char**>;
        my_exec("SELECT \"M\",e from orbital WHERE e < $1::double precision AND \"M\" < $2::double precision", 
          e_restriction, M_restriction);
      
          return 0;
      }
      

      【讨论】:

      • “但应该可以,不是吗?” - 不,不应该。提示:模板函数不允许部分特化。
      猜你喜欢
      • 2017-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多