2017-11-04 311 views
6

'de yanlış paket genişletilmiş. Variadic şablonlarla çok garip bir problemim var. Yanlış paket genişletilmiş görünüyor. İşteVariadic template

struct HasForward { int forward() { return 0; } }; 

struct Derived : Base<types<HasForward>> {}; 

First snippet live var: paket içinde değerlere sahip olduğunda

13 : <source>:13:43: error: request for member 'forward' in 'args2#0', which is of non-class type 'const char [7]' 
     -> decltype(std::make_tuple(args1.forward()..., std::declval<Args2>()...)) 
            ~~~~~~^~~~~~~ 
13 : <source>:13:43: error: request for member 'forward' in 'args2#0', which is of non-class type 'const char [7]' 
<source>: In function 'int main()': 
22 : <source>:22:27: error: unable to deduce 'auto' from '& construct<const char (&)[7]>' 
    auto test = &Derived::construct<char const(&)[7]>; 
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 
22 : <source>:22:27: note: could not resolve address from overloaded function '& construct<const char (&)[7]>' 
Compiler exited with result code 1 

Ancak, olmaz:

#include <tuple> 

template<typename...> 
struct types {}; 

template<typename = types<>> 
struct Base; 

template<typename... Args1> 
struct Base<types<Args1...>> { 
    template<typename... Args2> 
    static auto construct(Args1... args1, Args2&&... args2) 
     -> decltype(std::make_tuple(args1.forward()..., std::declval<Args2>()...)) 
    { 
     return std::make_tuple(args1.forward()..., std::forward<Args2>(args2)...); 
    } 
}; 

struct Derived : Base<> {}; 

int main() { 
    auto test = &Derived::construct<char const(&)[7]>; 
} 

bu hatayı alıyorum: İşte bir kod parçacığı İşte ve

Bu kodun nesi yanlış? Bu bir derleyici hatası mı? Üstesinden gelmenin ve ilk paketi boş bırakmanın bir yolu var mı?

+0

Benim clang ++ sorunsuz derlemek; Sanırım bu bir g ++ hatası. – max66

cevap

3

Is this a compiler bug? Is there any ways to overcome it and leave the first pack empty?

Derleyicinizde bir hataya benziyor.

template<typename... Args1> 
class Base<types<Args1...>> { 
    template<typename... T, typename... U> 
    static auto ret(types<T...>, types<U...>) 
    -> decltype(std::make_tuple(std::declval<T>().forward()..., std::declval<U>()...)); 

public: 
    template<typename... Args2> 
    static auto construct(Args1... args1, Args2&&... args2) 
    -> decltype(ret(types<Args1...>{}, types<Args2...>{})) 
    { 
     return std::make_tuple(args1.forward()..., std::forward<Args2>(args2)...); 
    } 
}; 

Biraz çirkin ama it works ilk paketi geçerli:
Eğer parametreleri test etmek için aşağıdaki örnekte olduğu gibi bir işlevi bildirimi (gerekli hiçbir tanım) kullanmak ve kullanabilirsiniz etrafında çözüm için boş (ayrıca istendiği gibi C++ 11) ve her şey linker tarafından atılmalıdır.

--- DÜZENLEME @ W.F önerdiği gibi

. yorumlarda (öneri için teşekkürler, fark etmedim), bunu başarmak daha da kolay. aşağıdaki gibi
Sadece işlevi tanımlayın:

static auto construct(Args1... args1, Args2&&... args2) 
    -> decltype(std::make_tuple(std::declval<Args1>().forward()..., std::declval<Args2>()...)) 
{ 
    return std::make_tuple(args1.forward()..., std::forward<Args2>(args2)...); 
} 
+0

da daha da basittir: std :: declval () .forward() ... 'işe yarıyor. OPs kodu kötü biçimlendirilmiş yapmak için zihin deneyini denedi ama aynı zamanda başarısız oldu. –

+0

@ W.F. İyi bir nokta. Ben fark etmedim. Cevabınızı entegre etmek için önerinizi kullanabilir miyim? – skypjack

+1

Elbette devam edin! ... –