2017-03-27 73 views
1

我有一个非模板类中的模板功能,像这样的模板函数:错误调用非模板类C++

class Foo 
{ 
    public: 
    template <class T> 
    void func(T& val) 
    { 
    //do work here 
    } 
} 

然后,在main.cpp中我做:

Foo a; 
std::string val; 
a.func<std::string>(val); //this line gives the error 

我收到一个错误,说“之前预计的主要表达”>'“。所以我做了快速谷歌搜索,发现每个人都提出一个简单的解决方案:

a.template func<std::string>(val); 

唯一的问题是,我仍然得到完全相同的错误。

编辑:

我不给完整的例子,是因为它涉及的是掩盖了问题的外部库和冗长的代码,但由于简化上面的代码不剪。下面是我写的完整的类:

class ConfigFileReader 
{ 
public: 
    ConfigFileReader() { } 

    ConfigFileReader(const std::string& config_file_path) 
    { 
     setConfigFilePath(config_file_path); 
    } 

    ~ConfigFileReader() { } 

    void setConfigFilePath(const std::string& config_file_path) 
    { 
    try 
    { 
     root_node_ = YAML::LoadFile(config_file_path); 
    } 
    catch(const YAML::BadFile& file_load_exception) 
    { 
     printf("Error opening YAML file. Maybe the file path is incorrect\n%s", file_load_exception.msg.c_str()); 
    } 

    } 

    template<class T> 
    bool getParam(const std::string& param_key, T& param_value) 
    { 
     if (root_node_.IsNull() || !root_node_.IsDefined()) 
     { 
      printf("Root node is undefined or not set"); 
      return false; 
     } 

     YAML::Node node = YAML::Clone(root_node_); 

     std::vector<std::string> split_name; 
     boost::split(split_name, param_key, boost::is_any_of("/")); 

     for(const std::string& str: split_name) 
     { 
      if (!node.IsMap()) 
      { 
       std::cout << "Parameter was not found (Node is null)." << str << std::endl; //replace with printf 
       return false; 
      } 

      node = node[str]; 
     } 

     if (node.IsNull() || !node.IsDefined()) 
     { 
      std::cout << "Parameter was not found (Node is null/undefined)." << std::endl; 
      return false; 
     } 

     try 
     { 
      param_value = node.as<T>(); 
      return true; 
     } 
     catch (const YAML::TypedBadConversion<T>& type_conversion_exception) 
     { 
      std::cout << "Error converting param value into specified data type" << std::endl; 
      std::cout << type_conversion_exception.msg << std::endl; 
     } 

     return false; 
    } 

private: 
    YAML::Node root_node_; 
}; 

然后,在一个单独的CPP文件的主要功能是

int main(int argc, char** argv) 
{ 
if (argc != 2) 
{ 
    printf("Incorrect number of arguments given"); 
    return EXIT_FAILURE; 
} 

printf("Config file path: %s", argv[1]); 

ConfigFileReader config_file_reader(std::string(argv[1])); 

std::string param_out; 

bool success = config_file_reader.template getParam<std::string>("controller/filepath", param_out); //<-- ERROR HERE 

return EXIT_SUCCESS; 
} 

编译: GCC 4.8.4,和C++ 11标志设置时编译。

编辑2: 添加到代码的字符串参数构造函数。

+3

[无法重现](http://coliru.stacked-crooked.com/a/ece8129982db7ee2)。你忘了包括''? – Quentin

+0

包含库。 – Ali250

+2

您需要创建一个[最小,完整和可验证示例](http://stackoverflow.com/help/mcve)并向我们显示。 –

回答

2

您的问题是这样的:

ConfigFileReader config_file_reader(std::string(argv[1])); 

被解释为一个名为config_file_reader函数接受一个指向字符串预先声明。看到错误消息:

ConfigFileReader(STD :: __ cxx11 ::字符串*){又名ConfigFileReader(STD :: __ cxx11 :: basic_string的*)}”

这是因为你以前遇到过The most vexing parse

使用ConfigFileReader config_file_reader(std::string{argv[1]});可以更好地消除您打算构造对象的编译器的歧义。然后编译器会开始抱怨你缺少一个接受字符串的构造函数!

有一个默认的构造函数,所以当我们使用:

ConfigFileReader config_file_reader; 

它的工作原理没有问题。

所以:

  1. 定义ConfigFileReader一个构造函数,接受string,然后
  2. 调用它以这样一种方式,代码是明确的

Demo

+0

这是调用*最令人头疼的解析*。 – Jarod42

+0

*“这是因为您实际上没有接受字符串的ConfigFileReader的构造函数。”*这不是原因。这只是一个解析问题。 – Jarod42

+0

@ Jarod42:我最初放弃了这个想法,但回过头来看,你是对的。 – AndyG

1

这是更简单:

Foo a; 
std::string val; 
a.func(val); // The compiler assumes T = std::string 
+4

显式模板参数也应该工作 - - 他们这样做。 OP的问题并不完整。 – Quentin

+0

用原来的代码编辑问题 – Ali250