Visual studio - std::enable_if 上的解决方法错误 c2770
Visual studio - workaround error c2770 on std::enable_if
从这里获取答案:iterate over tuple 关于打印 std::tuple
组件,这里是代码:
template<std::size_t I = 0, typename... Tp>
typename std::enable_if<I == sizeof...(Tp), void>::type
print(const std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
typename std::enable_if<I < sizeof...(Tp), void>::type
print(const std::tuple<Tp...>& t)
{
std::cout << std::get<I>(t) << std::endl;
print <i, Tp...> (t);
}
这可以在 GCC 上完美编译和运行,但无法在 VC++ 上编译(我使用 visual studio 2013)。我遇到的错误:
Error 4 error C2893: Failed to specialize function template 'std::enable_if<I==1,void>::type print(const std::tuple<_Types1...> &)'
Error 3 error C2770: invalid explicit template argument(s) for 'std::enable_if<I<1,void>::type print(const std::tuple<_Types1...> &)'
显然,在将 std::enable_if
与显式模板参数一起使用时,C2770 上存在一个已记录的错误。一些开发人员建议使用 const int
作为模板的前置参数,如
const int i = I+1;
print<i,Tp...>(t);
但这也不起作用。
还有其他解决方案,例如使用一些宏,但它们也失败了。
有人有解决办法吗?我搜索了一个解决方案,但发现 none 确实有效。
谢谢。
您可以使用以下其中一项:
使用递减递归和(部分)专业化:
namespace detail
{
template <std::size_t N>
struct printer
{
template <typename TUPLE>
void operator () (const TUPLE& t) const
{
printer<N - 1>{}(t);
std::cout << std::get<N - 1>(t) << std::endl;
}
};
template <>
struct printer<0>
{
template <typename TUPLE>
void operator () (const TUPLE& t) const {}
};
}
template <typename ... Ts>
void print(const std::tuple<Ts...>& t)
{
detail::printer<sizeof...(Ts)>{}(t);
}
或使用index_sequence
#if 1 // Not in C++11
#include <cstdint>
template <std::size_t...> struct index_sequence {};
template <std::size_t N, std::size_t... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {};
template <std::size_t... Is>
struct make_index_sequence<0u, Is...> : index_sequence<Is...>{};
#endif
namespace detail
{
template <std::size_t... Is, typename TUPLE>
void print(const TUPLE& t, index_sequence<Is...>)
{
int dummy[] = {0, ((std::cout << std::get<Is>(t) << std::endl), 0)...};
(void) dummy; // To remove warning about unused variable.
}
}
template <typename ... Ts>
void print(const std::tuple<Ts...>& t)
{
detail::print(t, make_index_sequence<sizeof...(Ts)> {});
}
为了保留问题中给出的原始代码的结构,以下解决方法适用于 MSVC 2013:
定义以下助手:
// workaround for msvc `sizeof...(Tp)` not working
template<typename... Tp>
struct sizeof_pack___ { static const std::size_t value = sizeof...(Tp); };
然后将出现的两次sizeof...(Tp)
替换为sizeof_pack___<Tp...>::value
。
最终代码如下所示:
template<std::size_t I = 0, typename... Tp>
typename std::enable_if<I == sizeof_pack___<Tp...>::value, void>::type
print(const std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
typename std::enable_if<I < sizeof_pack___<Tp...>::value, void>::type
print(const std::tuple<Tp...>& t)
{
std::cout << std::get<I>(t) << std::endl;
print <i, Tp...> (t);
}
从这里获取答案:iterate over tuple 关于打印 std::tuple
组件,这里是代码:
template<std::size_t I = 0, typename... Tp>
typename std::enable_if<I == sizeof...(Tp), void>::type
print(const std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
typename std::enable_if<I < sizeof...(Tp), void>::type
print(const std::tuple<Tp...>& t)
{
std::cout << std::get<I>(t) << std::endl;
print <i, Tp...> (t);
}
这可以在 GCC 上完美编译和运行,但无法在 VC++ 上编译(我使用 visual studio 2013)。我遇到的错误:
Error 4 error C2893: Failed to specialize function template 'std::enable_if<I==1,void>::type print(const std::tuple<_Types1...> &)'
Error 3 error C2770: invalid explicit template argument(s) for 'std::enable_if<I<1,void>::type print(const std::tuple<_Types1...> &)'
显然,在将 std::enable_if
与显式模板参数一起使用时,C2770 上存在一个已记录的错误。一些开发人员建议使用 const int
作为模板的前置参数,如
const int i = I+1;
print<i,Tp...>(t);
但这也不起作用。
还有其他解决方案,例如使用一些宏,但它们也失败了。
有人有解决办法吗?我搜索了一个解决方案,但发现 none 确实有效。
谢谢。
您可以使用以下其中一项:
使用递减递归和(部分)专业化:
namespace detail { template <std::size_t N> struct printer { template <typename TUPLE> void operator () (const TUPLE& t) const { printer<N - 1>{}(t); std::cout << std::get<N - 1>(t) << std::endl; } }; template <> struct printer<0> { template <typename TUPLE> void operator () (const TUPLE& t) const {} }; } template <typename ... Ts> void print(const std::tuple<Ts...>& t) { detail::printer<sizeof...(Ts)>{}(t); }
或使用
index_sequence
#if 1 // Not in C++11 #include <cstdint> template <std::size_t...> struct index_sequence {}; template <std::size_t N, std::size_t... Is> struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {}; template <std::size_t... Is> struct make_index_sequence<0u, Is...> : index_sequence<Is...>{}; #endif namespace detail { template <std::size_t... Is, typename TUPLE> void print(const TUPLE& t, index_sequence<Is...>) { int dummy[] = {0, ((std::cout << std::get<Is>(t) << std::endl), 0)...}; (void) dummy; // To remove warning about unused variable. } } template <typename ... Ts> void print(const std::tuple<Ts...>& t) { detail::print(t, make_index_sequence<sizeof...(Ts)> {}); }
为了保留问题中给出的原始代码的结构,以下解决方法适用于 MSVC 2013:
定义以下助手:
// workaround for msvc `sizeof...(Tp)` not working
template<typename... Tp>
struct sizeof_pack___ { static const std::size_t value = sizeof...(Tp); };
然后将出现的两次sizeof...(Tp)
替换为sizeof_pack___<Tp...>::value
。
最终代码如下所示:
template<std::size_t I = 0, typename... Tp>
typename std::enable_if<I == sizeof_pack___<Tp...>::value, void>::type
print(const std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
typename std::enable_if<I < sizeof_pack___<Tp...>::value, void>::type
print(const std::tuple<Tp...>& t)
{
std::cout << std::get<I>(t) << std::endl;
print <i, Tp...> (t);
}