可变参数模板继承中的类型不匹配

时间:2016-06-05 15:44:49

标签: c++ templates c++11 gcc variadic-templates

我有一个模板,它将参数列表中给出的模板应用于参数包中的所有类型并继承所有类型(称为ApplyOnPack):

<parent>
   <groupId>org.apache.camel</groupId>
   <artifactId>maven-plugins</artifactId> 
   <version>2.15.1.redhat-621107</version>
</parent>
<artifactId>camel-maven-plugin</artifactId>

问题是,最后一个base()方法不会使用gcc(4.9.2)编译声明无效的引用初始化。返回类型应该是* this类型的基类之一,那么可能是什么问题?或者我如何修改代码以使其可编译?该代码在msvc(2013)下编译和工作。

我用以下示例对其进行了测试:

template<template<int, typename> class Template, typename Seq, typename... Args>
struct _Map {};

template<template<int, typename> class Template,
         int firstIndex, int... indexes,
         typename First, typename... Args>
struct _Map<Template, Seq<firstIndex, indexes...>, First, Args...>
    : Template<firstIndex, First>,
      _Map<Template, Seq<indexes...>, Args...>
{};

template<template<int, typename> class Template, typename... Args>
struct ApplyOnPack : _Map<Template, Sequence<sizeof...(Args)>, Args... > 
{
    template <int I>
    struct Base {
        typedef Template<I, GetNthParameter<I, Args...> > Type;
    };

    template <int I>
    typename Base<I>::Type& base() { return *this; }
};

哪个gcc失败了:

template <int i, typename T>
struct Part {
    void foo() {}
};

template <typename ... T>
struct Foo : ApplyOnPack<Part, T...>
{
    void bar() { this->template base<0>().foo();  }
};

typedef Foo<int, bool> MyFoo;

int main() {
    MyFoo myFoo;
    myFoo.bar();
}

遵循上面使用的其他模板: 用于从参数包中提取第n个参数的模板(GetNthParameter):

a.cpp: In instantiation of ‘typename ApplyOnPack<Template, Args>::Base<I>::Type& ApplyOnPack<Template, Args>::base() [with int I = 0; Template = Part; Args = {int, bool}; typename ApplyOnPack<Template, Args>::Base<I>::Type = Part<0, int>]’:

a.cpp:62:15:   required from ‘void Foo<T>::bar() [with T = {int, bool}]’
a.cpp:69:12:   required from here
a.cpp:51:43: error: invalid initialization of reference of type ‘ApplyOnPack<Part, int, bool>::Base<0>::Type& {aka Part<0, int>&}’ from expression of type ‘ApplyOnPack<Part, int, bool>’
  typename Base<I>::Type& base() { return *this; }

和一个用于构建整数序列(Sequence):

template <int I, class... T>
struct _GetNthParameter;

template <int I, class Head, class... Tail>
struct _GetNthParameter<I, Head, Tail...>
    : _GetNthParameter<I-1, Tail...>{};

template <class Head, class... Tail>
struct _GetNthParameter<0, Head, Tail...> {
    typedef Head Type;
};

template<int index, typename... Types>
using GetNthParameter = typename _GetNthParameter<index, Types...>::Type;

1 个答案:

答案 0 :(得分:2)

您的类型不匹配。 Seq需要一大堆unsigned s:

template <unsigned...>
struct Seq { typedef int value_type; };

但是你专注于它需要一堆int s:

template<template<int, typename> class Template,
         int firstIndex, int... indexes, // <==
         typename First, typename... Args>
struct _Map<Template, Seq<firstIndex, indexes...>, First, Args...>

那些需要排队的人。 Clang接受代码,但这是一个铿锵的bug(#28010)。

正如我在评论中提到的,您使用的是标准保留的许多标识符。任何以下划线开头并后跟大写字母的单词都是保留的:不要使用它们!