Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用递归类模板在C++11中写出元组的内容?_C++_Templates_C++11_Stl_Tuples - Fatal编程技术网

如何使用递归类模板在C++11中写出元组的内容?

如何使用递归类模板在C++11中写出元组的内容?,c++,templates,c++11,stl,tuples,C++,Templates,C++11,Stl,Tuples,我尝试了以下递归来写出元组的元素,但在编译时计算元组大小的行中遇到了问题,如下所述: #include <tuple> #include <string> #include <iostream> template<typename Tuple, std::size_t element = 0> struct write_tuple { static void execute(Tuple const & t) {

我尝试了以下递归来写出元组的元素,但在编译时计算元组大小的行中遇到了问题,如下所述:

#include <tuple>
#include <string>
#include <iostream>

template<typename Tuple, std::size_t element = 0>
struct write_tuple
{
    static void execute(Tuple const & t)
    {
        std::cout << std::get<element>(t) << std::endl; 
        write_tuple<Tuple, element + 1>::execute(t); 
    }
};

template<typename Tuple>
struct write_tuple<Tuple, 4>  // This works fine
//struct write_tuple<Tuple, std::tuple_size<typename Tuple>::value >  // std::tuple_size should give me the size of the tuple at compile-time
{
    static void execute(Tuple const & t) {}; 
};

template<typename Tuple>
void write(Tuple const & t)
{
    write_tuple<Tuple>::execute(t); 
}

using namespace std;

int main(int argc, const char *argv[])
{
    tuple<string, int, double, string> myTuple = std::make_tuple("test", 0, 2.1, "finished"); 

    write(myTuple);

    return 0;
}
我使用的是GCC4.8.2

编辑:

从std::tuple\u size::value中删除typename会导致以下错误:

main.cpp:17:57: error: template argument 1 is invalid
     struct write_tuple<Tuple, std::tuple_size<typename Tuple>::value >  // std::tuple_size should give me the size of the tuple at compile-time
                                                             ^
main.cpp:17:66: error: template argument 2 is invalid
     struct write_tuple<Tuple, std::tuple_size<typename Tuple>::value >  // std::tuple_size should give me the size of the tuple at compile-time
g++ -std=c++11 main.cpp -o main  2>&1 | tee log 
main.cpp:17:8: error: template argument ‘std::tuple_size<_Tp>::value’ involves template parameter(s)
 struct write_tuple<Tuple, std::tuple_size<Tuple>::value>  // std::tuple_size should give me the size of the tuple at compile-time

这是语言的一个怪癖:非类型参数值不能依赖于专门化中的类型参数值。标准化委员会可能有原因。这可能是个好消息


有几种方法可以解决您的问题,最简单的方法是递归到0并在返回递归的过程中打印。对代码进行最少更改的一个方法是向类模板添加一个,typename=void>参数,并在专门化中添加size in,然后在专门化的末尾添加size,typename std::enable_if::type>。这使得测试在一个类型参数中进行,该参数在void上进行了专门化,void始终存在,但只有在SFINAE成功且大小与元组大小匹配时才有效。

这是语言的一个怪癖:非类型参数值不能依赖于专门化中的类型参数值。标准化委员会可能有原因。这可能是个好消息


有几种方法可以解决您的问题,最简单的方法是递归到0并在返回递归的过程中打印。对代码进行最少更改的一个方法是向类模板添加一个,typename=void>参数,并在专门化中添加size in,然后在专门化的末尾添加size,typename std::enable_if::type>。这使得测试在一个类型参数中进行,该参数在void上专用,它始终存在,但只有在SFINAE成功且大小与元组大小匹配时才有效。

对于您的代码,您可以反转递归,如:

template<typename Tuple, std::size_t remaining>
struct write_tuple
{
    static void execute(Tuple const & t)
    {
        std::cout << std::get<std::tuple_size<Tuple>::value - remaining>(t) << std::endl;
        write_tuple<Tuple, remaining - 1>::execute(t);
    }
};

template<typename Tuple>
struct write_tuple<Tuple, 0>
{
    static void execute(Tuple const & t) {};
};

template<typename Tuple>
void write(Tuple const & t)
{
    write_tuple<Tuple, std::tuple_size<Tuple>::value>::execute(t);
}
另一种办法:

#include <tuple>
#include <iostream>
#include <cstdint>

#if 1 // Not in C++11

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<0, Is...> : index_sequence<Is...> {};

#endif // make_index_sequence

template<typename Tuple>
struct write_tuple
{
    static void execute(Tuple const & t)
    {
        execute(t, make_index_sequence<std::tuple_size<Tuple>::value>());
    }

private:
    template<std::size_t ... Is>
    static void execute(Tuple const & t, index_sequence<Is...>)
    {
        const int dummy[] = {0, (write_element(std::get<Is>(t)), 0)...};
        static_cast<void>(dummy); // silent warning for unused variable.
    }

    template <typename T>
    static void write_element(T const &elem)
    {
        std::cout << elem << std::endl;
    }
};

对于您的代码,您可以反转递归,如:

template<typename Tuple, std::size_t remaining>
struct write_tuple
{
    static void execute(Tuple const & t)
    {
        std::cout << std::get<std::tuple_size<Tuple>::value - remaining>(t) << std::endl;
        write_tuple<Tuple, remaining - 1>::execute(t);
    }
};

template<typename Tuple>
struct write_tuple<Tuple, 0>
{
    static void execute(Tuple const & t) {};
};

template<typename Tuple>
void write(Tuple const & t)
{
    write_tuple<Tuple, std::tuple_size<Tuple>::value>::execute(t);
}
另一种办法:

#include <tuple>
#include <iostream>
#include <cstdint>

#if 1 // Not in C++11

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<0, Is...> : index_sequence<Is...> {};

#endif // make_index_sequence

template<typename Tuple>
struct write_tuple
{
    static void execute(Tuple const & t)
    {
        execute(t, make_index_sequence<std::tuple_size<Tuple>::value>());
    }

private:
    template<std::size_t ... Is>
    static void execute(Tuple const & t, index_sequence<Is...>)
    {
        const int dummy[] = {0, (write_element(std::get<Is>(t)), 0)...};
        static_cast<void>(dummy); // silent warning for unused variable.
    }

    template <typename T>
    static void write_element(T const &elem)
    {
        std::cout << elem << std::endl;
    }
};

将std::tuple\u size::value更改为std::tuple\u size::value。typename关键字在该上下文中无效。@user1353535:谢谢,我已经试过了,请参见编辑的问题。它无法推断专门化。看,更好的方法是从tuple_size倒计时到0,而不是从0到tuple_size倒计时@user1353535:谢谢你提出的另一个问题,我正在阅读。将std::tuple\u size::value更改为std::tuple\u size::value。typename关键字在该上下文中无效。@user1353535:谢谢,我已经试过了,请参见编辑的问题。它无法推断专门化。看,更好的方法是从tuple_size倒计时到0,而不是从0到tuple_size倒计时@用户1353535:谢谢你的另一个问题,我正在读。