Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.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++ 在块范围内重复使用非类型模板参数_C++_Templates_C++17 - Fatal编程技术网

C++ 在块范围内重复使用非类型模板参数

C++ 在块范围内重复使用非类型模板参数,c++,templates,c++17,C++,Templates,C++17,我有以下代码片段: template <size_t N> foo make() { ... } ... for (...) { auto foo = make<1>(); // lots of tests involving foo } 我想用非类型模板参数的不同值重复后一个块,例如make、make等 如果这是我想要迭代的类型,我可以使用,但不清楚我是否可以用相同的方式将非类型模板参数与泛型lambda一起使用 如何将其分解,以便创建并运行上面的

我有以下代码片段:

template <size_t N>
foo make() { ... }

...

for (...) {
    auto foo = make<1>();
    // lots of tests involving foo
}
我想用非类型模板参数的不同值重复后一个块,例如make、make等

如果这是我想要迭代的类型,我可以使用,但不清楚我是否可以用相同的方式将非类型模板参数与泛型lambda一起使用


如何将其分解,以便创建并运行上面的代码块,但使用不同的非类型参数值实例化make。解决方案应仅使用块作用域元素-如果我可以创建一些顶级模板struct maker{…}对象来包装make,那么这很容易。

作为手动索引列表的起点:

template <size_t N> int make();

template<> int make<1>() { std::cout<< "First" << std::endl; return 100; }
template<> int make<2>() { std::cout << "Second" << std::endl; return 200; }
template<> int make<3>() { std::cout << "Third" << std::endl; return 100; }

struct ExecuteInOrder { ExecuteInOrder( ... ) {} };

template < typename T>
void CallTest(T t )
{
    std::cout << "Your test code goes here...: " << t << std::endl;
}

    template< size_t ... N >
void Do()
{
    ExecuteInOrder {(CallTest(make<N>()),1)...};
}

int main()
{
    Do<1,2,3>();
}
或者,您可以简单地将其设置为递归,然后像这样先使用索引,后使用索引:

template < size_t FIRST, size_t LAST >
void ExecuteAndTest()
{
    auto foo = make<FIRST>();
    std::cout << "Here we go with the test" << foo << std::endl;

    // go for next step
    if constexpr ( LAST != FIRST ) { ExecuteAndTest<FIRST+1, LAST>(); }
}

int main()
{
    // first and last index of integer sequence
    ExecuteAndTest<1,3>();
}
最后总是从1到N

    template < size_t FIRST, size_t LAST >
void ExecuteAndTest_Impl()
{   
    auto foo = make<FIRST>();
    std::cout << "Here we go with the test" << foo << std::endl;

    // go for next step
    if constexpr ( LAST!= FIRST) { ExecuteAndTest_Impl<FIRST+1, LAST>(); }
}

    template < size_t LAST > 
void ExecuteAndTest()
{   
    ExecuteAndTest_Impl<1,LAST>();
}   

int main()
{   
    // or always start with 1 to n inclusive
    ExecuteAndTest<3>();
}  

作为手工编制索引列表的起点:

template <size_t N> int make();

template<> int make<1>() { std::cout<< "First" << std::endl; return 100; }
template<> int make<2>() { std::cout << "Second" << std::endl; return 200; }
template<> int make<3>() { std::cout << "Third" << std::endl; return 100; }

struct ExecuteInOrder { ExecuteInOrder( ... ) {} };

template < typename T>
void CallTest(T t )
{
    std::cout << "Your test code goes here...: " << t << std::endl;
}

    template< size_t ... N >
void Do()
{
    ExecuteInOrder {(CallTest(make<N>()),1)...};
}

int main()
{
    Do<1,2,3>();
}
或者,您可以简单地将其设置为递归,然后像这样先使用索引,后使用索引:

template < size_t FIRST, size_t LAST >
void ExecuteAndTest()
{
    auto foo = make<FIRST>();
    std::cout << "Here we go with the test" << foo << std::endl;

    // go for next step
    if constexpr ( LAST != FIRST ) { ExecuteAndTest<FIRST+1, LAST>(); }
}

int main()
{
    // first and last index of integer sequence
    ExecuteAndTest<1,3>();
}
最后总是从1到N

    template < size_t FIRST, size_t LAST >
void ExecuteAndTest_Impl()
{   
    auto foo = make<FIRST>();
    std::cout << "Here we go with the test" << foo << std::endl;

    // go for next step
    if constexpr ( LAST!= FIRST) { ExecuteAndTest_Impl<FIRST+1, LAST>(); }
}

    template < size_t LAST > 
void ExecuteAndTest()
{   
    ExecuteAndTest_Impl<1,LAST>();
}   

int main()
{   
    // or always start with 1 to n inclusive
    ExecuteAndTest<3>();
}  

在这种情况下,正确的工具是使用


在这种情况下,正确的工具是使用

您可以尝试以下方法:

#include <utility>
#include <cassert>

struct Foo
{ 
    Foo() {}
    Foo(std::size_t i) : i(i) {}
    std::size_t i;
};

template <std::size_t... Is>
void setFoo(std::size_t i, Foo& foo, std::index_sequence<Is...>)
{
    ((i == Is && (foo = Foo{Is}, false)), ...);
}

int main()
{
    for (std::size_t i = 0; i < 10; i++)
    {
        Foo foo;
        setFoo(i, foo, std::make_index_sequence<10>{});
        assert(foo.i == i);
    }
}
您可以尝试以下方法:

#include <utility>
#include <cassert>

struct Foo
{ 
    Foo() {}
    Foo(std::size_t i) : i(i) {}
    std::size_t i;
};

template <std::size_t... Is>
void setFoo(std::size_t i, Foo& foo, std::index_sequence<Is...>)
{
    ((i == Is && (foo = Foo{Is}, false)), ...);
}

int main()
{
    for (std::size_t i = 0; i < 10; i++)
    {
        Foo foo;
        setFoo(i, foo, std::make_index_sequence<10>{});
        assert(foo.i == i);
    }
}

那么,你有终止索引吗?你确定要从1开始而不是从0开始吗?@Nicolas-在这种情况下,我想从1开始,但如果0的解决方案更干净,我可以适应。终止索引是~10,但我也可以手动列出案例,比如{bar,bar,…}或其他什么,但不复制for循环中的所有代码。那么,您有终止索引吗?你确定要从1开始而不是从0开始吗?@Nicolas-在这种情况下,我想从1开始,但如果0的解决方案更干净,我可以适应。{10}但对于所有情况,我都是手动终止的,{10}但不是手动终止的。