Template options that depend on other template options?

I found several similar questions (like this ), but none of them answered my questions. Consider this piece of code:

template<unsigned int rows, unsigned int cols,typename arrtype>
class Variance
{
   double f(const arrtype &);
};

template<unsigned int rows, unsigned int cols>
double Variance<rows,cols,Eigen::Matrix<double,rows,cols>>
    ::f(const Eigen::Array<double,rows,cols> & M) 
{
  //do stuff
}

As you can see in the specialization, the type arrtypewill depend on rowsand cols. The above code leads to a compiler error (g ++ 5.4.0):

invalid use of incomplete typeclass Variance<rows, cols, Eigen::Matrix<double, rows, cols> >

I tried typename arrtype<rows, cols>in the template declaration, but then it complains that arrtypeit is not a type, which makes sense.

What is the correct way to use template types that depend on other template types?

+4
source share
2 answers

This is a simplified version of your code:

template<size_t rows, size_t cols> struct Foo {   double foo(); };

template<size_t rows> double Foo<rows,3>::f() { return 3;}

You will get the error:

error: invalid use of incomplete type ‘struct Foo<rows, 3ul>’
double Foo<rows,3>::f() { return 3;}

, , , .

:

template<size_t rows, size_t cols> struct Foo {   double foo(); };

template<size_t rows> struct Foo<rows,3> { double f() { return 3;}  };
+5

, , user463035818 answer ( ) , tagged dispatch.

, .

, Eigen::Array<double, rows, cols>:

template<unsigned int rows, unsigned int cols,typename arrtype>
class Variance
{
public:
    double f(const arrtype& arg)
    {
        return f_impl(arg, tag<arrtype>{});
    }
private:
    template<class... T>
    struct tag{};

    template<class... T>
    double f_impl(const arrtype&, tag<T...>){
        std::cout << "catch-all function\n";
        return 42.0;
    }

    double f_impl(const arrtype&, tag<Eigen::Array<double, rows, cols>>){
        std::cout << "specialization for Eigen::Array<double, rows, cols>\n";
        return 1337.0;
    }
};

:

Variance<1, 1, int> non_specialized;
non_specialized.f(int{}); // prints "catch-all function"

Variance<1, 1, Eigen::Array<double, 1, 1>> specialized;
specialized.f(Eigen::Array<double, 1, 1>{}); // prints "specialization for Eigen::Array<double, rows, cols>"


, , , - .

+4

Source: https://habr.com/ru/post/1696287/


All Articles