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

iav*_*avr 6 c++ gcc template-meta-programming c++11

以下适用类型转换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;
Run Code Online (Sandbox Code Playgroud)

现在,给出这个输入:

template <typename T> using map1 = T*;
template <typename T> using map2 = const T;
template <typename T> using map3 = const T*;
Run Code Online (Sandbox Code Playgroud)

我在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)
Run Code Online (Sandbox Code Playgroud)

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

我尝试过各种各样的组合.const T当作为输入类型映射给出时,除了地图之外,一切都有效apply.但如果我把它嵌入到定义中apply,那么仍然可行typedef C <const E...> type.

另一方面,一切都按照预期的方式运作.我可能会遗漏一些东西,但它对我来说真的像gcc bug.

有任何想法吗?

Dan*_*rey 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 >();    
}
Run Code Online (Sandbox Code Playgroud)

将无法链接,因为

undefined reference to `void dummy<A<int> >()'
Run Code Online (Sandbox Code Playgroud)

而不是预期的

undefined reference to `void dummy<A<const int> >()'
Run Code Online (Sandbox Code Playgroud)

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