我正在尝试为std::tuple
中的每个值调用一个函数,当然没有办法迭代元组,因此我使用iterate over tuple中讨论的模板技术
但是,我使用的是Visual Studio 2013,它不支持表达式SFINAE,因此代码不起作用。我试图基于常数(例如5,4,3,2,1,0)对模板进行部分专门化,但没有取得任何成功。我当然不是模板专家,所以我希望有人可以帮助我。我的表达式SFINAE代码如下。
#include <iostream>
#include <tuple>
using namespace std;
struct ArgPush {
void push(bool x) {}
void push(int x) {}
void push(double x) {}
void push(const char* x) {}
void push(const std::string& x) {}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
push_tuple(const std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
push_tuple(const std::tuple<Tp...>& t)
{
push(std::get<I>(t));
push_tuple<I + 1, Tp...>(t);
}
};
int main() {
ArgPush().push_tuple(std::make_tuple(1,2,3,4));
ArgPush().push_tuple(std::make_tuple("hello", "msvc makes me sad", 4, true));
return 0;
}
答案 0 :(得分:3)
MSVC不喜欢在enable_if
内进行的等式比较。所以将它们从那里移到辅助模板上。然后你的代码在VS2013上编译。
template<std::size_t I, typename... Tp>
struct comparator
{
static const bool value = (I < sizeof...(Tp));
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<!comparator<I, Tp...>::value>::type
push_tuple(const std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<comparator<I, Tp...>::value>::type
push_tuple(const std::tuple<Tp...>& t)
{
push(std::get<I>(t));
push_tuple<I + 1, Tp...>(t);
}
答案 1 :(得分:2)
您可以部分专业化而不是SFINAE:
template <std::size_t N>
struct helper
{
template <typename T>
static void push(T&& v)
{
// do something
}
template <typename ...Types>
static void push_tuple(const std::tuple<Types...>& t)
{
push(std::get<sizeof...(Types) - N>(t));
helper<N - 1>::push_tuple(t);
}
};
template <>
struct helper<0>
{
template <typename ...Types>
static void push_tuple(const std::tuple<Types...>&)
{
// nothing (end of iteration)
}
};
template <typename ...Types>
void push_tuple(const std::tuple<Types...>& t)
{
helper<sizeof...(Types)>::push_tuple(t);
}