2017-03-27 98 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