2011-11-13 6 views
1

Possible Duplicate:
trailing return type using decltype with a variadic template functionC++ 11バラード加算関数のこの実装で何が問題になっていますか?

私はこのコンパイラエラーを取得しています:このsum.cppため

g++ -std=gnu++0x -I. -O3 -Wall sum.cpp 
sum.cpp:7:41: sorry, unimplemented: cannot expand ‘Remaining ...’ into a fixed-length argument list 
sum.cpp: In function ‘int main(int, const char**)’: 
sum.cpp:29:23: error: no matching function for call to ‘sum(int, int, int)’ 
sum.cpp:29:23: note: candidate is: 
sum.cpp:20:6: note: template<class FirstArg, class ... RemainingArgs> decltype (Sum<FirstArg, RemainingArgs ...>::sum(first, sum::args ...)) sum(const FirstArg&, const RemainingArgs& ...) 

#include <iostream> 
#include <type_traits> 

template <typename First, typename... Remaining> 
struct Sum { 
    static auto sum(const First &arg, const Remaining &... args) 
     -> decltype(arg + Sum<Remaining...>::sum(args...)) 
    { 
     return arg + sum(args...); 
    } 
}; 

template <typename First> 
struct Sum<First> 
{ 
    static First sum(const First &arg) { return arg; } 
}; 

template <typename FirstArg, typename... RemainingArgs> 
auto sum(const FirstArg &first, const RemainingArgs &... args) 
    -> decltype(Sum<FirstArg, RemainingArgs...>::sum(first, args...)) 
{ 
    return Sum<FirstArg, RemainingArgs...>::sum(first, args...); 
} 

int main(int argc, const char *argv[]) 
{ 
    using ::std::cout; 
    cout << sum(1, 2, 3) << '\n'; 

    return 0; 
} 

私はこの関数を宣言し、複数の手段を試してみました。これはgcc 4.6.1の問題ですか?


編集:ここではは、私は本当に::std::common_typeテンプレートを信用していないので、私は最終的に一緒に行ったものです。それでも問題はありますが、左から右の代わりに右から左に+をバインドします。これは、非可換型+オペレータに問題を引き起こす可能性があります。それはしかし修正するのは非常に難しいことではありません。

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

namespace { 
template<class T> typename ::std::add_rvalue_reference<T>::type val(); 

template<class T> struct id{typedef T type;}; 

template<class T, class... P> struct sum_type; 
template<class T> struct sum_type<T> : id<T> {}; 
template<class T, class U, class... P> struct sum_type<T,U,P...> 
: sum_type< decltype(val<const T&>() + val<const U&>()), P... > {}; 
} 

template <typename T> 
T sum(const T &&arg) 
{ 
    return ::std::forward<const T>(arg); 
} 

template <typename FirstArg, typename SecondArg, typename... RemainingArgs> 
auto sum(const FirstArg &&first, const SecondArg &&second, 
     const RemainingArgs &&... args) 
    -> typename sum_type<FirstArg, SecondArg, RemainingArgs...>::type 
{ 
    using ::std::forward; 

    return forward<const FirstArg>(first) + \ 
     sum(forward<const SecondArg>(second), 
      forward<const RemainingArgs>(args)...); 
} 

int main(int argc, const char *argv[]) 
{ 
    using ::std::cout; 
    cout << sum(1, 2, 3.2) << '\n'; 

    return 0; 
} 
+2

短い答えを:あなたはトレーリング戻り値型で定義している非常に関数テンプレートの 'decltype'を使用することはできません、それはまだ宣言されていないからです。 – aschepler

+0

おっと、私はこれがあまりにも早く重複していると思いました。実際、私はここでわずかな問題しか見ませんが、そのアイデアはうまくいくかもしれません。 – aschepler

+0

FYI、GCCがここで不平を言っている実装されていない機能は、4.7のために実装されています。 –

答えて

6

再帰的に呼び出されています最初のインナーsum関数が間違った署名を持っています。実行時可変引数関数の場合

、この試してみてください。

#include <type_traits> 
#include <utility> 

template <typename T> T sum(T && x) { return std::forward<T>(x); } 

template <typename T, typename ...Args> 
typename std::common_type<T, Args...>::type sum(T && x, Args &&... args) 
{ 
    return std::forward<T>(x) + sum(std::forward<Args>(args)...); 
} 


int main() 
{ 
    return sum(1,2,3,4); 
} 
+0

コンパイル時に型が(もちろん)知られていても、実行時にしか知られていない値の束を合計します。 – Omnifarious

+0

@Omnifarious:OK、これをやり直してください。現在のコードはとにかく動作しません。戻ってきます。 –

+0

OK、まったく新しい答え! –

関連する問題