当前位置: 首页 > 知识库问答 >
问题:

如何定义变量类模板的成员模板函数

陈知
2023-03-14

我试图用成员模板函数实现一个可变类模板,其模板参数独立于类模板参数,但在定义成员模板时遇到了问题。

我将问题简化为尝试编译此文件(抱歉,无法进一步简化):

#include <iostream>
#include <string>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
#include <utility>
#include <vector>

template <class... Types>
class Foo {
public:
  Foo();

  template <class T>
  T& at(const std::string& key);

  template <class T>
  void insert(const std::string& key, const T& value);

private:
  std::tuple<std::unordered_map<std::string, Types>...> sets_;
  std::unordered_map<std::type_index, size_t> type_to_pos_;
};

template<class... Types>
Foo<Types...>::Foo() {
  std::vector<std::type_index> type_indices{std::type_index(typeid(Types))...};
  for (size_t i = 0; i < type_indices.size(); i++) {
    this->type_to_pos_.insert({type_indices[i], i});
  }
}

template<class T, class... Types>
T& Foo<Types...>::at(const std::string& key) {
  std::type_index type_idx{std::type_index(typeid(T))};
  size_t pos;

  pos = this->type_to_pos_.at(type_idx);
  return std::get<pos>(this->sets_).at(key);
}

template <class T, class... Types>
void Foo<Types...>::insert(const std::string& key, const T& value) {
  std::type_index type_idx{std::type_index(typeid(T))};
  size_t pos;

  pos = this->type_to_pos_.at(type_idx);
  std::get<pos>(this->sets_).insert({key, value});
}

int main(int argc, char** argv) {
  Foo<int, float, double> foo{};
  foo.insert("key", 1.0f);
  std::cout << foo.at<float>("key") << std::endl;
  return 0;
}

在尝试编译(C 11)时,我遇到以下错误:

$ make
Scanning dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/main.cpp.o
/Users/Jasper/cpp_projects/playground/main.cpp:33:19: error: nested name specifier 'Foo<Types...>::'
      for declaration does not refer into a class, class template or class template partial
      specialization
T& Foo<Types...>::at(const std::string& key) {
   ~~~~~~~~~~~~~~~^
/Users/Jasper/cpp_projects/playground/main.cpp:37:9: error: invalid use of 'this' outside of a
      non-static member function
  pos = this->type_to_pos_.at(type_idx);
        ^
/Users/Jasper/cpp_projects/playground/main.cpp:38:24: error: invalid use of 'this' outside of a
      non-static member function
  return std::get<pos>(this->sets_).at(key);
                       ^
/Users/Jasper/cpp_projects/playground/main.cpp:38:40: error: use of undeclared identifier 'key'
  return std::get<pos>(this->sets_).at(key);
                                       ^
/Users/Jasper/cpp_projects/playground/main.cpp:42:21: error: nested name specifier 'Foo<Types...>::'
      for declaration does not refer into a class, class template or class template partial
      specialization
void Foo<Types...>::insert(const std::string& key, const T& value) {
     ~~~~~~~~~~~~~~~^
/Users/Jasper/cpp_projects/playground/main.cpp:43:19: error: redefinition of 'type_idx'
  std::type_index type_idx{std::type_index(typeid(T))};
                  ^
/Users/Jasper/cpp_projects/playground/main.cpp:34:19: note: previous definition is here
  std::type_index type_idx{std::type_index(typeid(T))};
                  ^
/Users/Jasper/cpp_projects/playground/main.cpp:44:10: error: redefinition of 'pos'
  size_t pos;
         ^
/Users/Jasper/cpp_projects/playground/main.cpp:35:10: note: previous definition is here
  size_t pos;
         ^
/Users/Jasper/cpp_projects/playground/main.cpp:46:9: error: invalid use of 'this' outside of a
      non-static member function
  pos = this->type_to_pos_.at(type_idx);
        ^
8 errors generated.
make[2]: *** [CMakeFiles/test.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/test.dir/all] Error 2
make: *** [all] Error 2

我很确定它归结为第一个和第五个错误,但不知道我做错了什么。为什么Foo

编辑:添加实用程序库和固定返回值的插入

为了简单起见,我删除了所有异常检查。

--------@songyuanyao给出的答案解决了这个问题,但正如@songyuanyao指出的,get在编译时不知道pos,因此它不会编译。解决这个问题有助于解决这个问题。


共有1个答案

梁丘洲
2023-03-14

您应该指定两组模板参数:一组用于封闭类模板,另一组用于成员函数模板本身。例如。

template<class... Types> // for the enclosing class template
template<class T>        // for the member template
T& Foo<Types...>::at(const std::string& key) {
  ...
}

template<class... Types> // for the enclosing class template
template<class T>        // for the member template
void Foo<Types...>::insert(const std::string& key, const T& value) {
  ...
}
 类似资料:
  • 我试图在变量函数模板上使用'decltype'来获取其返回值类型,然后使用它来定义成员变量。但我一直在犯这样的错误: 基本上,decltype失败并将声明为int,而不是推断的返回类型。 它的工作原理是当我提供的所有参数的值,但这不是我要找的行为。因为我不知道该函数有多少参数,所以它必须保持为可变模板函数。 我计划如何使用类模板的示例: 如果我没有任何成员变量,并使用作为: 它编译,因此我相信能够

  • 我有一个模板化的C++类,它也有一个模板化的成员函数。这个成员函数的模板参数以特定的方式依赖于类的模板参数(请参阅下面的代码)。我正在为其模板参数的两个不同值实例化(而不是专门化)该类。一切都在这一点上进行。但是,如果我调用模板化的成员函数,对第一个实例化对象的调用只会编译,而不会编译第二个。似乎编译器没有为模板类的第二次实例化实例化模板化成员函数。我正在使用“g++filename.cpp”编译

  • 是否有人知道此显式特化是否有效: clang 主干 (12/3/2013) 给出以下错误: f:...\test.cpp:36:20: 错误: 从类 'O' 中出线定义 “Fun” 没有定义 1生成错误。 任何来自标准的支持参考来证明你的答案将不胜感激! 注意:我有点惊讶这是一个错误——我认为应该为任何以< code >开始实例化“Fun”的模板参数族选择专门化 这是一个叮当的错误还是我期望中的错

  • 我很难弄清楚如何使用适当的模板化参数调用setValue函数。在ParameterBase抽象基类中不可能有模板化的参数。非常感谢任何帮助。 附注。我没有使用boost::any的灵活性。

  • 我试图重写模板类http://docs.ros.org/hydro/api/rviz/html/c/message__filter__display_8h_source.html使用多种消息类型,使用变量模板。 我的第一个问题是如何使用可变模板重写下面的示例代码,以便它可以用于任意数量的模板参数,而不仅仅是2个。 我需要在家长类: 每个模板类型的虚拟成员函数 每个模板类型的每个的成员函数 每个模板

  • 正如我们已经描述过的,模板可以使用在数据模型中定义的变量。 在数据模型之外,模板本身也可以定义变量来使用。 这些临时变量可以使用FTL指令来创建和替换。请注意每一次的 模板执行 工作都维护它自己的私有变量, 同时来渲染页面。变量的初始值是空,当模板执行工作结束这些变量便被销毁了。 可以访问一个在模板里定义的变量,就像是访问数据模型根root上的变量一样。 这个变量比定义在数据模型中的同名参数有更高