模板化向下转换到派生类并调用相应的方法

Hua*_*ang 0 c++ templates smart-pointers c++17

我在 main.cpp 中有一个例程,用户将在其中指定要在程序中执行的模式。一旦指定了模式,就会执行相应的块——首先将父求解器向下转换为子求解器,并调用solve子类中的关联方法。

    std::unique_ptr<SudokuSolver> solver;
    if (mode == MODES::SEQUENTIAL_BACKTRACKING) 
    {
        solver = std::make_unique<SudokuSolver_SequentialBacktracking>();
        SudokuSolver_SequentialBacktracking* child_solver = dynamic_cast<SudokuSolver_SequentialBacktracking*>(solver.get());
        child_solver->solve(board);
    } 
    else if (mode == MODES::SEQUENTIAL_BRUTEFORCE)
    {
        solver = std::make_unique<SudokuSolver_SequentialBruteForce>();
        SudokuSolver_SequentialBruteForce* child_solver = dynamic_cast<SudokuSolver_SequentialBruteForce*>(solver.get());
        child_solver->solve(board);
    }   
    else if (mode == MODES::PARALLEL_BRUTEFORCE)
    {
        int NUM_THREADS = (argc >= 5) ? std::stoi(argv[4]) : 2;
        omp_set_num_threads(NUM_THREADS);
        
        #pragma omp parallel
        {
            #pragma omp single nowait
            {
                solver = std::make_unique<SudokuSolver_ParallelBruteForce>();
                SudokuSolver_ParallelBruteForce* child_solver = dynamic_cast<SudokuSolver_ParallelBruteForce*>(solver.get());
                child_solver->solve(board);
            }
        }
    }
    else if (mode == MODES::SEQUENTIAL_DANCINGLINKS)
    {
        solver = std::make_unique<SudokuSolver_SequentialDLX>(board);
        SudokuSolver_SequentialDLX* child_solver = dynamic_cast<SudokuSolver_SequentialDLX*>(solver.get());
        child_solver->solve();
    }
    else if (mode == MODES::PARALLEL_DANCINGLINKS)
    {
        int NUM_THREADS = (argc >= 5) ? std::stoi(argv[4]) : 2;
        omp_set_num_threads(NUM_THREADS);

        #pragma omp parallel
        {
            #pragma omp single
            {
                solver = std::make_unique<SudokuSolver_ParallelDLX>(board);
                SudokuSolver_ParallelDLX* child_solver = dynamic_cast<SudokuSolver_ParallelDLX*>(solver.get());
                child_solver->solve();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我发现它有点重复代码,所以我想将它们模板化为:

template <typename T>
void downCastandSolve(std::unique_ptr<SudokuSolver> solver, SudokuBoard& board)
{
    solver = std::make_unique<T>(board);
    T* child_solver = dynamic_cast<T*>(solver.get());
    child_solver->solve();
}
Run Code Online (Sandbox Code Playgroud)

但是,我收到以下错误消息:

error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = SudokuSolver; _Dp = std::default_delete<SudokuSolver>]’
Run Code Online (Sandbox Code Playgroud)

不确定如何正确模板化代码部分。希望有人能帮忙!

Phi*_*970 5

如果solve函数是虚拟的,你会有更清晰的代码。

此外,构造函数或解决方法应接收板引用,但不能同时接收。使用单一方法使代码更易于理解,因为每个算法的工作方式相同。

std::unique_ptr<SudokuSolver> CreateSolver(MODES mode)
{
    switch (mode)
    {
        case MODES::SEQUENTIAL_BACKTRACKING:
            return std::make_unique<SudokuSolver_SequentialBacktracking>();
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

然后假设solve是虚拟的,代码恢复为:

auto solver = CreateSolver(mode);
solver->solve(board);
solver->get_solution();
Run Code Online (Sandbox Code Playgroud)

solve在适当的时候,任何并行的东西都应该隐藏在函数中。

通过编写这样的代码,阅读起来容易得多,而且您不需要额外的模板函数来共享代码,因为您从一开始就避免了重复。