简体   繁体   English

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

[英]Type mismatch in variadic template inheritance

I have a template which applies the template given in argument list to all of the types in a parameter pack and inherits all of them (called ApplyOnPack): 我有一个模板,它将参数列表中给出的模板应用于参数包中的所有类型,并继承所有类型(称为ApplyOnPack):

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; }
};

The problem is, that this last base() method won't compile with gcc (4.9.2) claiming invalid reference initialization. 问题是,最后一个base()方法不会使用gcc(4.9.2)进行编译,声称无效的引用初始化。 The return type should be one of the base classes of the type of *this, so what could be the problem? 返回类型应该是* this类型的基类之一,那么可能是什么问题? Or how can I modify the code to be compileable? 或者我如何修改代码以使其可编译? The code compiles and works under msvc (2013). 该代码在msvc(2013)下编译和工作。

I've tested it with the following example: 我用以下示例测试了它:

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();
}

Which gcc failed upon with: 哪个gcc失败了:

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; }

Following additional templates used above: A template (GetNthParameter) for extracting n-th parameter from a parameter pack: 以下使用的其他模板:用于从参数包中提取第n个参数的模板(GetNthParameter):

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;

and one for building integer sequence (Sequence): 和一个用于构建整数序列(序列):

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

template<unsigned max, unsigned... numbers>
struct _ExpandSeq : _ExpandSeq<max-1, max-1, numbers...> {};

template<unsigned... numbers>
struct _ExpandSeq<0, numbers...> {
  typedef Seq<numbers...> type;
};

template<unsigned max>
using Sequence = typename _ExpandSeq<max>::type;

You have a type mismatch. 您的类型不匹配。 Seq takes a bunch of unsigned s: Seq需要一堆unsigned s:

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

But you're specializing on it taking a bunch of int s: 但你专注于它需要一堆int

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

Those need to line up. 那些需要排队。 Clang accepts the code, but this is a clang bug ( #28010 ). Clang接受代码,但这是一个铿锵的bug( #28010 )。


As I mentioned in the comments, you are using many identifiers that are reserved by the standard. 正如我在评论中提到的,您使用的是标准保留的许多标识符。 Any word that starts with an underscore and is followed by a capital letter is reserved: don't use them! 保留任何以下划线开头并后跟大写字母的单词:不要使用它们!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM