2017-05-12 42 views
2

我试图延长的std :: vector类有特色的方法 :C++可变参数模板空包

template<typename... An> 
tuple<An...> get(); 

它应该返回指定的派生类类型的第一个出现在向量。

我发生了一些问题,扩大空模板包我发现这个线程:How to match empty arguments pack in variadic template,所以我修改了我的班,现在它看起来像这样:

template<typename T> 
class AggregationVector : public vector<T> 
{ 
    public: 
    template<typename A> 
    tuple<A> getSingle() 
    { 
     for (auto i = vector<T>::begin(); i != vector<T>::end(); i++) 
     { 
      A element = dynamic_cast<A>(*i); 
      if (element != nullptr) return make_tuple(element); 
     } 

     return make_tuple(nullptr); 
    } 

    template<typename A, typename... An> 
    tuple<A, An...> getHelper() 
    { 
     return tuple_cat(getSingle<A>(), get<An...>()); 
    } 

    template<typename... An> 
    tuple<An...> get() 
    { 
     return getHelper<An...>(); 
    } 

    template<> 
    tuple<> get<>() 
    { 
     return make_tuple(); 
    } 
}; 

不幸的是我仍然得到错误,我不知道如何解决这些问题:

Line 29: explicit specialization in non-namespace scope 'class AggregationVector<T>'| 
Line 30: template-id 'get<>' in declaration of primary template| 
    In instantiation of 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {}; T = AggregationVectorTest::Base*]':| 
Line 20: required from 'std::tuple<A, An ...> AggregationVector<T>::getHelper() [with A = AggregationVectorTest::DoubleDerived1*; An = {}; T = AggregationVectorTest::Base*]'| 
Line 26: required from 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {AggregationVectorTest::DoubleDerived1*}; T = AggregationVectorTest::Base*]'| 
Line 20: required from 'std::tuple<A, An ...> AggregationVector<T>::getHelper() [with A = AggregationVectorTest::Base*; An = {AggregationVectorTest::DoubleDerived1*}; T = AggregationVectorTest::Base*]'| 
Line 26: required from 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {AggregationVectorTest::Base*, AggregationVectorTest::DoubleDerived1*}; T = AggregationVectorTest::Base*]'| 
Line (this error points to line starting with "tuple<Base*, DoubleDerived1*> tup1" from example code): required from here| 
Line 26: error: no matching function for call to 'AggregationVector<AggregationVectorTest::Base*>::getHelper()'| 
Line 26: note: candidate is:| 
Line 18: note: template<class A, class ... An> std::tuple<A, An ...> AggregationVector<T>::getHelper() [with A = A; An = {An ...}; T = AggregationVectorTest::Base*]| 
Line 18: note: template argument deduction/substitution failed:| 
Line 26: note: couldn't deduce template parameter 'A'| 
    In member function 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {}; T = AggregationVectorTest::Base*]':| 
Line 27: warning: control reaches end of non-void function [-Wreturn-type]| 

我知道,我应该把上面的元组元组getHelper()方法的声明,但随后它给了我,get()方法不能被重载错误

'template<class T> template<class ... An> std::tuple<_Args1 ...> AggregationVector<T>::get()' cannot be overloaded| 
with 'template<class T> template<class ... An> std::tuple<_Args1 ...> AggregationVector<T>::get()'| 

我的示例代码来测试它看起来像这样:

// declaration of few polymorphic classes 
class Base 
{ 
    public: 
    int Value; 

    Base(int v = 0) { Value = v; } 

    virtual void write() 
    { 
     cout << "Base " << Value << endl; 
    } 

    virtual ~Base(); 
}; 
class Derived1 : public Base 
{ 
    public: 
    Derived1(int v = 0) : Base::Base(v) { } 

    virtual void write() 
    { 
     cout << "Derived1 " << Value << endl; 
    } 
}; 
class DoubleDerived1 : public Derived1 
{ 
    public: 
    DoubleDerived1(int v = 0) : Derived1::Derived1(v) { } 

    virtual void write() 
    { 
     cout << "DoubleDerived1 " << Value << endl; 
    } 
}; 
class Derived2 : public Base 
{ 
    public: 
    Derived2(int v = 0) : Base::Base(v) { } 

    virtual void write() 
    { 
     cout << "Derived2 " << Value << endl; 
    } 
}; 

//test implementation 
Base a1(1); 
Base a2(2); 
Derived1 b3(3); 
DoubleDerived1 bb4(4); 
Derived2 c5(5); 
Derived2 c6(6); 

AggregationVector<Base*> vec {&a1, &a2, &b3, &bb4, &c5, &c6}; 

tuple<Base*, DoubleDerived1*> tup1 = vec.get<Base*, DoubleDerived1*>(); 
tuple<Derived1*, DoubleDerived1*, Derived2*> tup2 = vec.get<Derived1*, DoubleDerived1*, Derived2*>(); 

cout << "Test Tuple1 result: " << (get<0>(tup1)->Value == 1 && get<1>(tup1)->Value == 4) << endl; 
cout << "Test Tuple2 result: " << (get<0>(tup2)->Value == 3 && get<1>(tup2)->Value == 4 && get<2>(tup2)->Value == 5) << endl; 
+0

[你不能专注的一个成员模板未特化的模板类](http://stackoverflow.com/a/5513109/501250)。无论如何,这些职能没有理由成为这个班的成员。他们可以轻松实现免费功能。 – cdhowie

+0

可变参数模板字符串的末尾应以'元组得到()'结尾,而不是空的。 – GLCraft

+1

@GLCraft两种方法都可以正常工作。 – cdhowie

回答

4

你不需要的get任何专长,只是

template<typename... An> 
tuple<An...> get() 
{ 
    return tuple_cat(getSingle<An>()...); 
} 
+0

谢谢!这正是我需要的解决方案。我刚开始处理可变参数模板,我不知道这个语法是可能的。 – Symeg