admin管理员组

文章数量:1355694

I have a following class:

template<typename Population, typename... Operators> class GA
{
public:
    template<typename Evaluator,
             typename std::enable_if_t<
             std::is_same_v<Evaluator, Evaluator<Operators...>>>>
  void EvaluatePopulation(Evaluator& evaluator)
  {
    evaluator.Evaluate();
  }
};

This doesn't compile, because of incorrect EvaluatePopulation declaration.

How do I specify that EvaluatePopulation method can be called only with Evaluator class that was initialized with the same Operators... as the GA class?

I have a following class:

template<typename Population, typename... Operators> class GA
{
public:
    template<typename Evaluator,
             typename std::enable_if_t<
             std::is_same_v<Evaluator, Evaluator<Operators...>>>>
  void EvaluatePopulation(Evaluator& evaluator)
  {
    evaluator.Evaluate();
  }
};

This doesn't compile, because of incorrect EvaluatePopulation declaration.

How do I specify that EvaluatePopulation method can be called only with Evaluator class that was initialized with the same Operators... as the GA class?

Share Improve this question edited Mar 30 at 20:17 JeJo 33.5k6 gold badges53 silver badges94 bronze badges asked Mar 30 at 17:21 PeterPeter 1111 silver badge8 bronze badges 1
  • Can't doublecheck the syntax right now but I think you just need a template-template parameter instead like template<template<typename...> Evaluator> void EvaluatePopulation(Evaluator<Operators...>& evaluator) – NathanOliver Commented Mar 30 at 17:26
Add a comment  | 

1 Answer 1

Reset to default 9

How do I specify that EvaluatePopulation method can be called only with Evaluator class that was initialised with the same Operators... as the GA class?

The trick is to use a template template parameter so that you “unpack” the evaluator’s template arguments to match the GA’s pack. For example, you can write:

template<typename Population, typename... Operators>
class GA
{
public:
    template<template<typename...> class EvaluatorT>
    void EvaluatePopulation(EvaluatorT<Operators...>& evaluator)
    {
        evaluator.Evaluate();
    }
};

((See live demo))


Alternatively, using c++20's concepts, which gives clearer error messages:

// Ensures Evaluator is instantiated with exactly Operators...
template<typename T, typename... Args>
constexpr bool is_evaluator_for_v = false;

template<template<typename...> class EvaluatorT, typename... Ops>
constexpr bool is_evaluator_for_v<EvaluatorT<Ops...>, Ops...> = true;

template<typename Evaluator, typename... Operators>
concept EvaluatorFor = is_evaluator_for_v<Evaluator, Operators...>;

template<typename Population, typename... Operators> class GA 
{
public:
    
    template<typename Evaluator> requires EvaluatorFor<Evaluator, Operators...>
    void EvaluatePopulation(Evaluator& evaluator) 
    {
        evaluator.Evaluate();
    }
};

((See live demo))

本文标签: cHow to constrain template methods to match class template parametersStack Overflow