jeudi 2 août 2018

Variadic function templates, argument order, and deduction

I'm trying to write a variadic template function which will construct a linear combination of Eigen matrices, taking advantage of the expression support. (Hence why I want to use a variadic template rather than a simple loop.)

However, I'm having a strange thing happen with the deduction of my template arguments. Here's a simplified code example:

#include <iomanip>
#include <iostream>
#include "eigen3/Eigen/Dense"

////////////////////////////////////////////////////////////////
// matrix linear combination
////////////////////////////////////////////////////////////////

template <typename Derived>
auto LinearCombination(
    const typename Eigen::MatrixBase<Derived>& matrix,
    const typename Eigen::internal::traits<Derived>::Scalar a
  ) -> decltype(a*matrix)
{
  return a*matrix;
}

template <typename Derived, typename... Args>
auto LinearCombination(
    const typename Eigen::MatrixBase<Derived>& matrix_a,
    const typename Eigen::internal::traits<Derived>::Scalar a,
    Args... args
  ) -> decltype(a*matrix_a + LinearCombination(args...))
{
  return a*matrix_a + LinearCombination(args...);
}


int main(int argc, char **argv)
{
  Eigen::MatrixXd m1, m2, m3;
  m1.resize(2,2);
  m2.resize(2,2);
  m3.resize(2,2);
  m1 << 1, 2,
        3, 4;
  m2 << 5, 6,
        7, 8;
  m3 << 9, 0,
        1, 2;

  std::cout << LinearCombination(m1, 2.) << std::endl << std::endl;
  std::cout << LinearCombination(m1, 2., m2, 3.) << std::endl << std::endl;
  std::cout << LinearCombination(m1, 1., m2, 2., m3, 1.5) << std::endl;

  // termination
  return 0;
}

For a reason which I don't understand, the first two function calls compile, while the third fails with

variadic-eigen.cpp(44): error: no instance of overloaded function "LinearCombination" matches the argument list
            argument types are: (Eigen::MatrixXd, double, Eigen::MatrixXd, double, Eigen::MatrixXd, double)
    std::cout << LinearCombination(m1, 1., m2, 2., m3, 1.5) << std::endl;
                 ^
variadic-eigen.cpp(19): note: this candidate was rejected because at least one template argument could not be deduced
  auto LinearCombination(
       ^
variadic-eigen.cpp(10): note: this candidate was rejected because mismatch in count of arguments
  auto LinearCombination(
       ^

Is there some part of the standard which I'm missing which leaves this behavior undefined?

Aucun commentaire:

Enregistrer un commentaire