我有一些代码对我来说似乎毫不含糊,但是gcc4.7对它很窒息:
#include <iostream>
#include <tuple>
using namespace std;
// Container for mixins
template<template<typename> class... Mixins>
struct Mix : Mixins<Mix<Mixins...>>... {
typedef tuple<Mixins<Mix<Mixins...>>...> types;
};
// Outer layer extracts the type tuple from the argument
template<typename T>
struct InnerCombiner {
typedef typename InnerCombiner<typename T::types>::type type;
};
// Typedef type to be a new mix of the inner mixins of the MixedMixins
template<typename... MixedMixins>
struct InnerCombiner<tuple<MixedMixins...>> {
// This line is the problem. The compiler doesn't seem to be able to make sense
// of the reference to the inner mixin template template classes
typedef Mix<MixedMixins::InnerMixin...> type;
};
template<typename Mixed>
struct A {
template<typename MixedInner>
struct InnerMixin {
void foo() { cout << "foo() loves you!" << endl; };
};
};
template<typename Mixed>
struct B {
template<typename MixedInner>
struct InnerMixin {
void bar() { cout << "bar() loves you!" << endl; };
};
};
// I'm going to write out the type I expect ic to have. Oh god, it's so nasty:
// Mix<
// A<Mix<A,B>>::InnerMixin<Mix<A<Mix<A,B>>::InnerMixin,B<Mix<A,B>>::InnerMixin>,
// B<Mix<A,B>>::InnerMixin<Mix<A<Mix<A,B>>::InnerMixin,B<Mix<A,B>>::InnerMixin>
// >
int main() {
InnerCombiner<Mix<A,B>>::type ic;
ic.bar(); // Not working.
}
以这种方式访问InnerMixins有什么问题吗?我写这篇文章时似乎很合理:)
答案 0 :(得分:4)
我可以通过指定InnerMixin模板使其在 clang 3.0 上运行:
typedef Mix<MixedMixins::template InnerMixin...> type;
// ^^^^^^^^
但是在g ++ 4.8上仍然无法使用
3.cpp:23:52: error: parameter packs not expanded with ‘...’: 3.cpp:23:52: note: ‘MixedMixins’
答案 1 :(得分:1)
存在类型/值不匹配,至少应为MixedMixins::template InnerMixin...
。然而海湾合作委员会仍然拒绝这一点,我发现没有办法哄骗它。不幸的是,我很难证明这样的包扩展实际上是有效的。希望更精通语法的人能够回答这一点。
在更“横向”的方法中,您是否考虑过完全抛弃模板模板参数?这不仅可以缓解语法的痛苦,而且还可以“重新绑定”模板专业化的模板参数:
// We accept two types, a template specialization and
// a sequence of would be template parameters.
template<typename Specialization, typename T>
struct rebind;
template<
template<typename...> class Template
, typename... Old
template<typename...> class Sequence
, typename... T
>
struct rebind<Template<Old...>, Sequence<T...>> {
using type = Template<T...>;
};
template<typename S, typename... T>
using Rebind = typename rebind<S, T...>::type;
E.g。 Rebind<std::vector<int>, std::tuple<double, std::allocator<double>>
是std:vector<double>
。将其与parameters_of
/ ParametersOf
实用程序相结合,将专业化的模板参数提取到例如std::tuple
。
作为免责声明,我自己并没有长时间使用这些技术,但我已经意识到如何将模板模板参数的痛点限制在我的代码的几个集中位置。