简体   繁体   English

调用非模板化类c ++的模板化函数时出错

[英]Error calling templated function of non-templated class c++

I have a templated function inside a non-templated class, like so: 我在非模板化的类中有一个模板化的函数,如下所示:

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

Then, in main.cpp I'm doing: 然后,在main.cpp中我正在做:

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

I get an error saying "primary expression expected before '>'" . 我收到一条错误,说“在'>'之前预期的主表达式” So I do a quick Google search and find that everyone suggests a simple solution: 所以我快速搜索谷歌,发现每个人都建议一个简单的解决方案:

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

Only problem is, I'm still getting the exact same error. 唯一的问题是,我仍然得到完全相同的错误。

EDIT : 编辑:

The reason I wasn't giving the full example is because it involves external libraries and lengthy code that obscures the question, but since the simplified code above doesn't cut it. 我没有提供完整示例的原因是因为它涉及外部库和冗长的代码,这些代码模糊了问题,但由于上面的简化代码没有削减它。 Here's the complete class that I wrote: 这是我写的完整课程:

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

Then, in a separate cpp file is the main function 然后,在一个单独的cpp文件中是main函数

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

Compiler: gcc 4.8.4, and c++11 flag set when compiling. 编译器: gcc 4.8.4,编译时设置c ++ 11标志。

EDIT 2: Added string argument constructor to the code. 编辑2:在代码中添加了字符串参数构造函数。

Your problem is that this: 你的问题是:

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

Is interpreted as a forward declaration for a function named config_file_reader that accepts a pointer to a string. 被解释为名为config_file_reader的函数的前向声明,该函数接受指向字符串的指针。 See the error message: 请参阅错误消息:

ConfigFileReader(std::__cxx11::string*) {aka ConfigFileReader(std::__cxx11::basic_string*)}' ConfigFileReader(std :: __ cxx11 :: string *){aka ConfigFileReader(std :: __ cxx11 :: basic_string *)}'

This is because you've encountered The most vexing parse 这是因为你遇到了最令人烦恼的解析

Use ConfigFileReader config_file_reader(std::string{argv[1]}); 使用ConfigFileReader config_file_reader(std::string{argv[1]}); to better disambiguate for the compiler that you are intending to construct an object. 为编译器更好地消除歧义,您打算构造一个对象。 Then the compiler will start complaining that you're missing a constructor that accepts a string! 然后编译器会开始抱怨你错过了一个接受字符串的构造函数!

You do have a default constructor, so when we use that: 有一个默认的构造函数,所以当我们使用:

ConfigFileReader config_file_reader;

It works without issue. 它没有问题。

So: 所以:

  1. define a constructor for ConfigFileReader that accepts a string , then 然后为ConfigFileReader定义一个接受string的构造函数
  2. Call it in such a way that the code is unambiguous 以这样的方式调用它,使代码明确无误

Demo 演示

It's even simpler: 它甚至更简单:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM