2014-05-13 38 views
3

我有以下代码:C++ 11奇怪的错误与模板功能

#include <iostream> 
#include <utility> 
#include <type_traits> 
#include <typeinfo> 

using namespace std; 


struct Void{ 
    static constexpr int size = 0; 
}; 

template<typename T0, typename T1> 
class Variadic{ 
private: 
    typedef Variadic<T0, T1> thisT; 

public: 
    /** Do not use this constructor */ 
    Variadic(T0 el0, T1 el1): value(el0), next(el1) {} 

    // avoiding decltype 
    typedef T0 valueT; 
    T0 value; 

    typedef T1 nextT; 
    T1 next; // may be next pair 

    /** 
    * Chainable method 
    */ 
    template<typename ValueT> 
    /*constexpr*/ inline Variadic<ValueT, thisT> add(ValueT value){ 
     return Variadic<ValueT, thisT>(value, (*this)); 
    } 

}; 

template<typename T> 
/*constexpr*/ static inline Variadic<T, Void> make_variadic(T value){ 
    return Variadic<T, Void>(value, Void()); 
} 



template<typename Arg0, typename... Args> 
static inline auto make_variadic(Arg0 value0, Args... values) -> decltype(fill(make_variadic<Arg0>(value0), values...)) { 
    return fill(make_variadic<Arg0>(value0), values...); 
} 

/* 
template<typename Arg0, typename... Args> 
static inline auto make_variadic(Arg0 value0, Args... values) -> decltype(fill(Variadic<Arg0, Void>(value0, Void()), values...)) { 
    return fill(Variadic<Arg0, Void>(value0, Void()), values...); 
}*/ 


template<typename T, typename Arg0, typename... Args> 
static inline auto fill(T self, Arg0 value, Args... values) -> decltype(fill(self.add(value), values...)){ 
    return fill(self.add(value), values...); 
} 

template<typename T, typename Arg0> 
static inline auto fill(T self, Arg0 value) -> decltype(self.add(value)){ 
    return self.add(value); 
} 



int main() 
{ 
    auto list = make_variadic(1, 2, 3); 
} 

代码IS http://coliru.stacked-crooked.com/a/bbacd7e9bec149f0

,当我尝试用gcc 4.8编译它,我得到以下错误:

expansion pattern '#'nontype_argument_pack' not supported by dump_expr#

这是http://open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1433还是https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51501

或者这是完全不同的东西?

+0

你怎么称呼你的编译器? – usr1234567

+0

我相信'静态内联自动填充(T self,Arg0值,Args ...值) - > decltype(fill(self.add(value),values ...))'无法编译,因为它是一个递归声明。函数的返回类型不能是函数本身的返回类型的decltype。 – Klaus

+0

在此处查看完整代码http://coliru.stacked-crooked.com/a/bbacd7e9bec149f0 – tower120

回答

1

谷歌搜索您的错误信息,这看起来相关的compiler bug它还原成关于后返回类型的known Defect Report

1433. trailing-return-type and point of declaration

Section: 3.3.2 [basic.scope.pdecl] Status: extension
Submitter: Jason Merrill Date: 2011-12-20 This seems like it should be well-formed:

template <class T> T list(T x); 

template <class H, class ...T> 
auto list(H h, T ...args) -> decltype(list(args...)); 


auto list3 = list(1, 2, 3); 

but it isn't, because the second list isn't in scope in its own trailing-return-type; the point of declaration is after the declarator, which includes the trailing-return-type. And since int has no associated namespaces, the call in the return type only sees the first list. G++, EDG and Clang all reject the testcase on this basis.

But this seems like a natural pattern for writing variadic function templates, and we could support it by moving the point of declaration to the ->. This would mean having to deal with a function that only has a placeholder for a return type, but I think we can handle that.

Rationale (February, 2012):

This is a request for an extension to the language and is thus more appropriately addressed by EWG.

+0

我也想过了,正如我在http://open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1433中所描述的那样。但是......为什么“填充”工作好于?它有相同的可变参数... – tower120

+0

对不起,我错过了你的Q(浏览器没有刷新)。 OTOH,Clang在Coliru上编译你的代码(如果你在未使用的'list'变量上禁用了这个警告)。 – TemplateRex

+0

是的,它编译,所以我做了一个bug gcc bugzilla https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61178,只是为了肯定:) – tower120