c++ - 如何定义可变参数类模板的成员模板函数
问题描述
我正在尝试使用其模板参数独立于类模板参数的成员模板函数来实现可变参数类模板,但是我在定义成员模板时遇到了麻烦。
我将我的问题简化为尝试编译它(抱歉无法弄清楚如何进一步简化):
#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<Types...>
引用类模板?我怎样才能解决这个问题?
编辑:添加实用程序库和固定的返回值insert
。
PS 为了简单起见,我删除了所有异常检查。
—————————- @songyuanyao 给出的答案解决了问题,但正如@songyuanyao 指出的那样,在编译时get
不知道pos
所以不会编译。这个解决方案有助于解决这个问题。
解决方案
您应该分开两组模板参数:一组用于封闭类模板,另一组用于成员函数模板本身。例如
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) {
...
}
推荐阅读
- javascript - GTM - 将 DataLayer 变量截断为自定义 Javascript 变量
- r - 尽管我遵循了此代码的模板,但我仍然收到此错误。有经验的人能发现我看不到的东西吗?我是 R 新手
- telegram - 电报机器人,报价=假问题
- react-native - 隐藏的标签栏在 React Native 应用程序中突出
- ssh - 使用 Plink 在另一台服务器 (jumphost) 后面的远程服务器上执行命令
- python - matplotlib 根据任意函数缩放轴
- javascript - 如何将 div 附加到呈现列表中的输入值?
- node.js - 在 Loopback 应用程序中发出请求时使用不同的错误消息
- java - 使用带有 Azure B2C 的 Spring Boot OAuth 2.0 的身份验证失败
- r - 使用拟合的计量经济学/统计模型来求解非线性方程