lundi 27 janvier 2020

Type deduction of parameter and parameter pack

I have the following code for generically wrapping Petsc objects in a unique_ptr, but it doesn't quite work the way I'd expect from cppreference's documentation on template type deduction: https://en.cppreference.com/w/cpp/language/class_template_argument_deduction.

template <typename obj_type, typename... constructor_args>
using petsc_cons = PetscErrorCode (*)(constructor_args..., obj_type *);

template <typename obj_type> using petsc_destr = PetscErrorCode (*)(obj_type *);

template <typename obj_type, typename... constructor_args>
auto petsc_make_unique(petsc_cons<obj_type, constructor_args...> construct,
                       petsc_destr<obj_type> destroy, constructor_args... args) {
  // allocation code...
}

class NLOptimizer {
public:
  NLOptimizer(const size_t num_vars)
      : tao_ctx(petsc_make_unique<Tao>(TaoCreate, TaoDestroy,
                                       PETSC_COMM_SELF)) {}

This fails on g++:

autodiff_tao.hpp: In constructor ‘auto_diff::optimize_tao::NLOptimizer<expr_t>::NLOptimizer(expr_t, size_t)’:
autodiff_tao.hpp:45:62: error: no matching function for call to ‘petsc_make_unique<Tao>(PetscErrorCode (&)(MPI_Comm, _p_Tao**), PetscErrorCode (&)(_p_Tao**), MPI_Comm)’
   45 |                                               PETSC_COMM_SELF)) // ,
      |                                                              ^
autodiff_tao.hpp:24:6: note: candidate: ‘template<class obj_type, class ... constructor_args> auto auto_diff::optimize_tao::petsc_make_unique(auto_diff::optimize_tao::petsc_cons<obj_type, constructor_args ...>, auto_diff::optimize_tao::petsc_destr<obj_type>, constructor_args ...)’
   24 | auto petsc_make_unique(petsc_cons<obj_type, constructor_args...> construct,
      |      ^~~~~~~~~~~~~~~~~
autodiff_tao.hpp:24:6: note:   template argument deduction/substitution failed:
autodiff_tao.hpp:45:62: note:   mismatched types ‘_p_Tao*’ and ‘ompi_communicator_t’
   45 |                                               PETSC_COMM_SELF)) // ,

Clang is able to deduce the parameter pack types and compiles the code above. Is this a bug in g++, clang, or am I relying on undefined behaviour here?

I've attempted this compilation on multiple minor versions of clang 9 and g++ 9, and several less successful variations of the code above.

Aucun commentaire:

Enregistrer un commentaire