将类型转换应用于列表:“const”特殊吗?

时间:2013-09-16 13:08:46

标签: c++ gcc c++11 template-meta-programming

以下内容将类型转换F应用于C类型的列表E...

template <template <typename...> class F, typename P> struct apply_t;

template <
    template <typename...> class F,
    template <typename...> class C, typename... E
> struct apply_t <F, C <E...> > { typedef C <F <E>...> type; };

template <template <typename...> class F, typename P>
using apply = typename apply_t<F, P>::type;

现在,给出这个输入:

template <typename T> using map1 = T*;
template <typename T> using map2 = const T;
template <typename T> using map3 = const T*;

我在gcc 4.8.1中得到以下输出,例如使用std::tuple

apply <map1, tuple <int, char> >  // -> tuple <int*, char*>  (OK)

apply <map2, tuple <int, char> >  // -> tuple <int, char>
  // (tuple <const int, const char> expected)

apply <map3, tuple <int, char> >  // -> tuple <const int*, const char*> (OK)

我可以使用调用static_assert()的实用程序模板函数来查看输出类型。

我尝试过各种各样的组合。当作为const T的输入类型地图给出时,除了地图apply之外,一切都有效。但如果我将其嵌入apply的定义,即typedef C <const E...> type,仍然可以正常工作。

另一方面,一切都按照预期的方式运作。我可能会遗漏一些东西,但这对我来说似乎是一个gcc bug。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

这是一个完整但缩减的测试用例,您可能希望将其添加到GCC错误报告中(如果您需要编写一个):

template< typename T > using Map = const T;

template< template<typename> class M, typename T >
struct Apply;

template< template<typename> class M, template<typename...> class C, typename... Ts >
struct Apply< M, C<Ts...> > { typedef C<M<Ts>...> type; };

template< typename T > struct A {};
template<typename> void dummy();

int main()
{
    dummy< Apply<Map,A<int>>::type >();    
}
由于

将无法链接

undefined reference to `void dummy<A<int> >()'

而不是预期的

undefined reference to `void dummy<A<const int> >()'

(我知道这并没有解决问题,但GCC人员可能更喜欢减少测试用例,而不依赖std::tuple或任何其他标题。)