2015-05-04 102 views
1

采取的答案从这里:iterate over tuple关于打印std::tuple成分,这里是代码:视觉工作室 - 性病解决方法错误c2770 :: enable_if

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...> &)' 

appearntly上有C2770一中的缺陷利用std::enable_if具有明确的模板参数时。一些开发商利用const int作为预参数为模板

const int i = I+1; 
print<i,Tp...>(t); 

推荐但这也不管用。 还有其他的解决方案,如使用一些宏,但它们也失败了。
有人有解决它的方法吗?我搜索了一个解决方案,但没有发现任何实际的工作。
谢谢。

+0

工作对我来说在VS2015 RC。发布(希望)即将推出,所以工具链升级可能是非标准的,但也是可行的选择。 (在VS2015中甚至没有提到'constexpr',更快的编译和链接等) – Drop

+0

感谢他们修正了它:) :) –

回答

1

您可以使用以下中的一个:使用递减递归和(部分)专业化

  • 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)> {}); 
    } 
    
+0

我没有试过第二个代码片段,但第一个defintly的作品。谢谢。 –

1

要保留这个问题给出的原始代码的结构,下面的解决办法适用于我在MSVC 2013:

定义下列助手:

// workaround for msvc `sizeof...(Tp)` not working 
template<typename... Tp> 
struct sizeof_pack___ { static const std::size_t value = sizeof...(Tp); }; 

然后用sizeof_pack___<Tp...>::value取代的sizeof...(Tp)出现的两个。

最后的代码应该是这样的:

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); 
}