首先,我认为如果顺序确实很重要,最好在调用之前显式构造这些元素,然后将它们传入。更容易阅读,但更不有趣!
这只是对 Kerrek 的回答的扩展:
#include <utility>
namespace detail
{
// the ultimate end result of the call;
// replaceable with std::result_of? I do not know.
template <typename F, typename... Args>
static auto ordered_call_result(F&& f, Args&&... args)
-> decltype(std::forward<F>(f)
(std::forward<Args>(args)...)); // not defined
template <typename R>
class ordered_call_helper
{
public:
template <typename F, typename... Args>
ordered_call_helper(F&& f, Args&&... args) :
mResult(std::forward<F>(f)(std::forward<Args>(args)...))
{}
operator R()
{
return std::move(mResult);
}
private:
R mResult;
};
template <>
class ordered_call_helper<void>
{
public:
template <typename F, typename... Args>
ordered_call_helper(F&& f, Args&&... args)
{
std::forward<F>(f)(std::forward<Args>(args)...);
}
};
// perform the call then coax out the result member via static_cast,
// which also works nicely when the result type is void (doing nothing)
#define ORDERED_CALL_DETAIL(r, f, ...) \
static_cast<r>(detail::ordered_call_helper<r>{f, __VA_ARGS__})
};
// small level of indirection because we specify the result type twice
#define ORDERED_CALL(f, ...) \
ORDERED_CALL_DETAIL(decltype(detail::ordered_call_result(f, __VA_ARGS__)), \
f, __VA_ARGS__)
还有一个例子:
#include <iostream>
int add(int x, int y, int z)
{
return x + y + z;
}
void print(int x, int y, int z)
{
std::cout << "x: " << x << " y: " << y << " z: " << z << std::endl;
}
int get_x() { std::cout << "[x]"; return 11; }
int get_y() { std::cout << "[y]"; return 16; }
int get_z() { std::cout << "[z]"; return 12; }
int main()
{
print(get_x(), get_y(), get_z());
std::cout << "sum: " << add(get_x(), get_y(), get_z()) << std::endl;
std::cout << std::endl;
ORDERED_CALL(print, get_x(), get_y(), get_z());
std::cout << "sum: " << ORDERED_CALL(add, get_x(), get_y(), get_z()) << std::endl;
std::cout << std::endl;
int verify[] = { get_x(), get_y(), get_z() };
}
最后一行是用来验证大括号初始值设定项实际上确实有效,通常情况下。
不幸的是,正如从其他答案/评论中发现的那样,GCC 没有做对,所以我无法测试我的答案。此外,MSVC Nov2012CTP 也没有正确处理(并且有一个令人讨厌的错误,扼杀了ordered_call_result
†)。如果有人想用clang测试这个,那就太好了。
†对于这个特定的例子,尾随返回类型可以decltype(f(0, 0, 0))
代替。