C++11 可变参数求和函数的实现有什么问题(如果有的话)?
可能的重复:
使用带有可变参数模板函数的 decltype 的尾随返回类型
我收到此编译器错误:
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& ...)
对于此 sum.cpp:
#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;
}
Possible Duplicate:
trailing return type using decltype with a variadic template function
I'm getting this compiler error:
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& ...)
for this sum.cpp:
#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;
}
I've tried multiple means of declaring this function. Is this just a problem with gcc 4.6.1?
Edit: Here is what I finally went with because I don't really trust the ::std::common_type
template. It still has a problem though, it will bind +
from right to left instead of from left to right. This may cause problems with non-commutative +
operators. That's not very hard to fix though:
#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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
递归调用的第一个内部
sum
函数的签名错误。对于运行时可变参数函数,请尝试以下操作:
The first inner
sum
function that's being called recursively has the wrong signature.For a run-time variadic function, try this: