从可变参数模板中的扩展 decltype 继承
Inheritance from expanded decltype in variadic template
我正在尝试C++模板元编程,试图创建一个具有以下语义的存储类:它接受任意数量的类型,并为每个类型存储一个具有通用访问接口的用户定义类型的容器。我能够使用以下代码从 decltype 扩展列表进行多重继承来实现它(A
和 B
只是要放入Storage
的虚拟结构(:
#include <iostream>
#include <string>
#include <map>
#include <unordered_map>
struct A
{
int v = -1;
};
struct B
{
std::string v;
};
typedef int Key;
template<typename T>
auto componentContainer();
template<>
auto componentContainer<A>()
{
return std::unordered_map<Key, A>();
}
template<>
auto componentContainer<B>()
{
return std::map<Key, B>();
}
template<typename... Component>
struct Storage : public decltype(componentContainer<Component>())...
{
template <typename T>
using Container = decltype(componentContainer<T>());
template<typename T>
T& get(int index)
{
return Container<T>::operator [](index);
}
template<typename T>
const T& get(int index) const
{
return Container<T>::operator [](index);
}
template<typename T>
void put(int index, const T& v)
{
Container<T>::operator [](index) = v;
}
template<typename T, typename F>
void apply(F f)
{
for (auto p = Container<T>::begin();
p != Container<T>::end();
p++)
{
f(p);
}
}
};
int main(int argc, char** argv)
{
Storage<A,B> s;
s.put<A>(0, {12});
s.put<A>(3, {42});
s.put<B>(0, {"melta"});
s.put<B>(42, {"multimelta"});
auto printer = [](auto p) { std::cout <<p->first <<": " << p->second.v <<std::endl;};
s.apply<A>(printer);
s.apply<B>(printer);
return 0;
}
此代码在 gcc 5.1.0 中编译良好并生成预期结果,但在 Visual Studio 2015 中无法编译,并显示以下错误消息:
main.cpp(37): error C2143: syntax error: missing ',' before '...'
main.cpp(70): note: see reference to class template instantiation 'Storage<Component...>' being compiled
main.cpp(37): error C3520: 'Component': parameter pack must be expanded in this context
main.cpp(74): note: see reference to class template instantiation 'Storage<A,B>' being compiled
main.cpp(37): error C3770: 'unknown-type': is not a valid base class
问题是,我不确定从这样的扩展 decltype 列表继承是否合法(即符合标准(。所以,我的问题是:
struct Storage: public decltype(componentContainer<Component>())...
标准C++是合法的还是 gcc 的功能?- 如果是,可以在Visual Studio中完成吗?
这在 MSVC 中对我有用。
template<typename T>
struct StorageBase
{
using Type = decltype(componentContainer<T>());
};
template<typename... Component>
struct Storage : public StorageBase<Component>::Type...
{ }
语法错误使我相信编译器在扩展参数包之前尝试评估decltype
表达式 - 因此它也发出'Component': parameter pack must be expanded in this context
。
通过使用StorageBase
来简化表达式,decltype
看起来可以完成这项工作。
你可以使用组合而不是继承(感谢std::tuple
(:
template <typename T>
using Container = decltype(componentContainer<T>());
template <typename... Components>
class Storage
{
public:
template<typename T>
T& get(int index) { return std::get<Container<T>>(t)[index]; }
template<typename T>
const T& get(int index) const { return std::get<Container<T>>(t).at(index); }
template<typename T>
void put(int index, const T& v) { std::get<Container<T>>(t)[index] = v; }
template<typename T, typename F>
void apply(F f)
{
for (const auto& p : std::get<Container<T>>(t))
{
f(p);
}
}
private:
std::tuple<Container<Components>...> t;
};
相关文章:
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 是否可以通过C++扩展强制多个python进程共享同一内存
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++decltype和圆括号-为什么
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 扩展光电二极管探测器以支持多个传感器
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 如何从"decltype()"获取函数参数的数量<funtion>?
- Confusion: decltype vs std::function
- C++中的VLA,扩展名为std=C++11
- OpenGL 和 GLM 矩阵无法正确扩展,总是按比例缩小
- decltype(1, t) 应该是 l 值引用吗?(编译器不同意)
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- C++返回 Numpy 数组的 Python 扩展模块
- 扩展可变参数模板中的变量名称
- 扩展C++生成的代码的模板参数类型名称
- 我想通过带有C++和Python的插件创建一个可扩展的应用程序
- VSCode IntelliSense无法识别SDL框架的SDL_image扩展库
- 如何通过扩展以下类型特征来删除 decltype(&MyClass::funct) 部分?
- 从可变参数模板中的扩展 decltype 继承