Search code examples
c++visual-studioeigencompiler-bug

Avoiding ambiguous parameters in templated Eigen functions with MSVS


I'm writing some funtions that are supposed to take Eigen::Array as an input. The Arrays are of constant size, but the size is a template parameter and should be deducted from the input. When compiling with MSVS, i have to supply the size to the function or it will result in an error.

#include <Eigen/Core>

template<unsigned short t_iSize>
void foo(const Eigen::Array<unsigned short, t_iSize, 1>&)
{

}

int main()
{
    Eigen::Array<unsigned short, 3, 1> test;
    // foo(test);    // Compiler errors C2672 and C2784
    foo<3>(test);    // Giving the size solves the errors
}

The size should be possible to be deducted from the variable test, but it seems to fail when computing the template arguments 4 and 5 for the Array.

Error C2672: "foo": no matching overloaded function found.

Error C2784: "void foo(const Eigen::Array< unsigned short,t_iSize,1,|_Rows==&&?:&&_Rows!=?:,_Rows,1> &)": could not deduce template argument for "const Eigen::Array< unsigned short,t_iSize,1,|_Rows==&&?:&&_Rows!=?:,_Rows,1> &" from "Eigen::Array< unsigned short,3,1,0,3,1>".

Is it possible to avoid this problem when taking the Eigen::Array, or do I need to take Eigen::ArrayBase as a function parameter? I would like to avoid that, as it obscures the fact that the function only takes this specific type of arrays.

Edit:

As Jarod42 noted, the template parameter should be of type int. Visual Studio can compile the code with this mistake. It fails in deducing the parameter _Rows, though, where other compilers can do so.

Here you can see the problem I ran into.


Solution

  • Declaration of Eigen::Array is

    template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
    class Eigen::Array;
    

    Your function uses wrong type for row, unsigned short should be int.

    template <int t_iSize>
    void foo(const Eigen::Array<unsigned short, t_iSize, 1>&)
    {
        // ...
    }
    

    Demo

    As workaround for your issue with Msvc, you might do:

    • apply the default value manually:

      template <int t_iSize>
      void bar(const Eigen::Array<unsigned short, t_iSize, 1, 0, t_iSize, 1>&) {
        // ...
      }
      
    • or add the extra template (and so the code is even more generic):

      template <int t_iSize, int Options, int MaxRows, int MaxCols>
      void foo(const Eigen::Array<unsigned short, t_iSize, 1, Options, MaxRows, MaxCols>&) {
        // ...
      }
      

    Demo