Повторное использование нетипичного параметра шаблона в области видимости блока - PullRequest
1 голос
/ 07 ноября 2019

У меня есть следующий фрагмент кода:

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

...

for (...) {
    auto foo = make<1>();
    // lots of tests involving foo
}

Я хотел бы повторить этот последний блок с другими значениями для параметра шаблона нетипичного типа make, например, make<2>, make<3> и т. Д.

Если бы это был тип, который я хотел бы перебрать, я мог бы использовать это решение , но не ясно, что я могу использовать не шаблонные параметры шаблона собщая лямбда тем же способом.

Как я могу это учесть, чтобы я мог создать приведенный выше блок кода, но создавал экземпляр make с другими значениями для его нетипового параметра. В решении должны использоваться только элементы блочной области видимости - это легко, если я смогу создать объект template <size_t N> struct maker { ... } верхнего уровня для переноса make.

Ответы [ 2 ]

2 голосов
/ 07 ноября 2019

В такой ситуации правильным инструментом является использование std :: integer_sequence

#include <iostream>
#include <utility>

template <size_t N>
void make()
{
  std::cout << N << std::endl;
}

template <size_t... I>
void do_make_helper(std::index_sequence<I...>)
{
  (make<I+1>(), ...); 
}

template <std::size_t N>
void do_make()
{
  do_make_helper(std::make_index_sequence<N>());
}

int main()
{
  do_make<10>();
}

printts

1
2
3
4
5
6
7
8
9
10
1 голос
/ 07 ноября 2019

В качестве начальной точки со списком индексов, созданных вручную:

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