2010-05-13 22 views
4

(相关C++0x, How do I expand a tuple into variadic template function arguments?GCC ICE - 替代函数的语法,可变参数模板和元组

下面的代码(见下文)从该discussion服用。目标是将函数应用于元组。我简化了模板参数并修改了代码以允许泛型类型的返回值。

虽然原来的代码编译细,当我试图编译GCC 4.4.3修改后的代码,

g++ -std=c++0x main.cc -o main

GCC报告以下消息内部编译器错误(ICE):

main.cc: In function ‘int main()’:
main.cc:53: internal compiler error: in tsubst_copy, at cp/pt.c:10077
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.4/README.Bugs> for instructions.

问题:代码是否正确?或者ICE是否被非法代码触发?

// file: main.cc 
#include <tuple> 

// Recursive case 
template<unsigned int N> 
struct Apply_aux 
{ 
    template<typename F, typename T, typename... X> 
    static auto apply(F f, const T& t, X... x) 
    -> decltype(Apply_aux<N-1>::apply(f, t, std::get<N-1>(t), x...)) 
    { 
    return Apply_aux<N-1>::apply(f, t, std::get<N-1>(t), x...); 
    } 
}; 

// Terminal case 
template<> 
struct Apply_aux<0> 
{ 
    template<typename F, typename T, typename... X> 
    static auto apply(F f, const T&, X... x) -> decltype(f(x...)) 
    { 
    return f(x...); 
    } 
}; 

// Actual apply function 
template<typename F, typename T> 
auto apply(F f, const T& t) 
    -> decltype(Apply_aux<std::tuple_size<T>::value>::apply(f, t)) 
{ 
    return Apply_aux<std::tuple_size<T>::value>::apply(f, t); 
} 

// Testing 
#include <string> 
#include <iostream> 

int f(int p1, double p2, std::string p3) 
{ 
    std::cout << "int=" << p1 << ", double=" << p2 << ", string=" << p3 << std::endl; 
    return 1; 
} 

int g(int p1, std::string p2) 
{ 
    std::cout << "int=" << p1 << ", string=" << p2 << std::endl; 
    return 2; 
} 

int main() 
{ 
    std::tuple<int, double, char const*> tup(1, 2.0, "xxx"); 
    std::cout << apply(f, tup) << std::endl; 
    std::cout << apply(g, std::make_tuple(4, "yyy")) << std::endl; 
} 

注:如果我硬编码在递归情况下返回类型(参见代码),那么一切都很好。也就是说,将此片段替换为递归情况不会触发ICE:

// Recursive case (hardcoded return type) 
template<unsigned int N> 
struct Apply_aux 
{ 
    template<typename F, typename T, typename... X> 
    static int apply(F f, const T& t, X... x) 
    { 
    return Apply_aux<N-1>::apply(f, t, std::get<N-1>(t), x...); 
    } 
}; 

唉,这是对原始问题的不完整解决方案。

+3

非法或不合法,ICE不应该发生。提交一个错误。 – kennytm 2010-05-13 17:57:05

+0

该错误已被提交。请参阅GCC Bugzilla Bug 44167(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44167)。欢呼声 – 2010-05-17 14:11:34

回答

2

我试过你在g ++ 4.6上的代码。由于缺少实现,它不能编译。然而,实现一般性的一种方法是将自由立场函数包装在std :: function包装中,并使用如下所示的typedef。

template<typename F, typename T> 
typename F::result_type apply(F f, const T& t) 
{ 
    ... 
} 
int f(int p1, double p2, std::string p3) 
{ 
    std::cout << "int=" << p1 << ", double=" << p2 << ", string=" << p3 << std::endl; 
    return 1; 
} 
int main() 
{ 
    std::tuple<int, double, char const*> tup(1, 2.0, "xxx"); 
    std::function<int (int, double, char const *)> func = &f; 
    std::cout << apply(func, tup) << std::endl; 

} 
+0

优雅的解决方案。不幸的是,我无法在GCC 4.4.3中使用它。我不知道为什么。如果我发现任何新东西,我会在这里发帖。干杯 – 2010-05-17 16:14:12

相关问题