【问题标题】:Error calling templated function of non-templated class c++调用非模板类 c++ 的模板函数时出错
【发布时间】:2023-03-24 04:39:01
【问题描述】:

我在非模板类中有一个模板函数,如下所示:

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文件中是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;
}

编译器: gcc 4.8.4,编译时设置c++11标志。

编辑 2: 在代码中添加了字符串参数构造函数。

【问题讨论】:

  • Cannot reproduce。您是否忘记包含&lt;string&gt;
  • 没有。包含 库。
  • 您需要创建一个Minimal, Complete, and Verifiable Example 并展示给我们。
  • template 在这里没用。我没有看到带有std::stringConfigFileReader 构造函数。请提供完整的错误信息
  • 顺便说一句,如果您不想包含完整示例,因为它涉及到外部库和冗长的代码会掩盖问题,那么您应该阅读minimal reproducible example

标签: c++ templates


【解决方案1】:

你的问题是这样的:

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

被解释为一个名为config_file_reader 的函数的前向声明,该函数接受一个指向字符串的指针。查看错误信息:

ConfigFileReader(std::__cxx11::string*) {aka 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

【讨论】:

  • 这是调用最令人头疼的解析
  • “这是因为您实际上没有接受字符串的 ConfigFileReader 的构造函数。” 这不是原因。这只是一个解析问题。
  • @Jarod42:我最初放弃了它的想法,但回头看后,你是对的。
  • 这解决了问题(终于)!谢谢你。另外,我在代码中添加了字符串参数构造函数,它只是调用setConfigFilePath
【解决方案2】:

更简单:

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

【讨论】:

  • 显式模板参数也应该起作用——而且它们确实起作用。 OP的问题不完整。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 2011-06-07
  • 2010-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多