C++ 用可变参数包实例化函数模板

C++ 用可变参数包实例化函数模板,c++,c++11,c++14,C++,C++11,C++14,假设我有以下代码: template<int... Us> struct Matrix{}; template<int... U1, int... U2> auto compute(Matrix<U1...>, Matrix<U2...>){return 0;} Matrix<1> a; Matrix<2,3> b; Matrix<1,2> c; Matrix<3> d; int main(){

假设我有以下代码:

template<int... Us>
struct Matrix{};

template<int... U1, int... U2>
auto compute(Matrix<U1...>, Matrix<U2...>){return 0;}

Matrix<1> a; Matrix<2,3> b;
Matrix<1,2> c; Matrix<3> d;

int main(){   
    compute(a,b);
    compute(c,d);
    auto fp = &compute<1,2,3>;
    fp(a,b);
    fp(c,d);
}
模板
结构矩阵{};
模板
自动计算(矩阵,矩阵){返回0;}
基质a;矩阵b;
矩阵c;矩阵d;
int main(){
计算(a,b);
计算(c,d);
自动fp=&compute;
fp(a,b);
fp(c,d);
}
两个compute()调用是只实例化一个函数模板,即compute,还是根据参数有两个不同的实例化

我想通过获取一个指向特定实例化的函数指针来确认这一点,并查看是否可以使用相同的函数指针使用两组不同的参数调用该函数,但在调用fp(a,b)的行中出现以下错误:

[x86-64 gcc 8.2#1]错误:无法从
“矩阵”到“矩阵”
这两个
compute()
调用是否仅实例化一个函数模板,即
compute
,或者是否根据参数有两个不同的实例化

非常不同。编写
compute(a,b)
时调用的函数是一个接受
矩阵和
矩阵的函数。编写
compute(c,d)
时调用的函数是一个接受
矩阵和
矩阵的函数

但当你写这篇文章时:

auto fp = &compute<1,2,3>;

这很管用(试试看),但却是一种完全不同的东西

参数包是贪婪的

&compute
在伪代码中是
&compute

获取单个计算机的指针很烦人

template<class U1s, class U2s>
struct get_computer;
template<int...U1, int...U2>
struct get_computer<std::integer_sequence<int, U1...>, std::integer_sequence<int, U2...>> {
  using compute_type = int(*)(Matrix<U1...>, Matrix<U2...>);
  compute_type operator()() const { return compute; }
};
模板
结构获取计算机;
模板
结构获取计算机{
使用compute_type=int(*)(矩阵,矩阵);
compute_type运算符()()常量{return compute;}
};
然后我们就可以做了

auto fp1 = get_computer<std::integer_sequence<int, 1>, std::integer_sequence<int, 2, 3>>{}();
auto fp2 = get_computer<std::integer_sequence<int, 1, 2>, std::integer_sequence<int, 3>>{}();
autofp1=get_computer{}();
auto fp2=get_computer{}();

fp1
fp2
是不同的类型。

不同的方法。不需要整数序列或临时函子对象。链接:

模板
结构Mat1{
模板
结构Mat2{
使用compute_type=int(*)(矩阵,矩阵);
};
};
void foo(){
{
使用compute\u type=Mat1::Mat2::compute\u type;
compute_类型ct=计算;
ct(a,b);
//ct(c,d);//这不会编译
}
{
使用compute\u type=Mat1::Mat2::compute\u type;
compute_类型ct=计算;
ct(c,d);
//ct(a,b);//这不会编译
}
}

甚至更通用

template<int... Us>
struct Matrix{};

Matrix<1> a; Matrix<2,3> b;
Matrix<1,2> c; Matrix<3> d;

template<int... U1, int... U2>
auto compute(Matrix<U1...>, Matrix<U2...>){return 0;}

template<class Scalar, template<Scalar...> class MatType>
struct VArg {
    template<Scalar... V1>
    struct arg1 {
        using type = MatType<V1...>;
        template<Scalar... V2>
        struct arg2 {
            using type1 = type;
            using type2 = MatType<V2...>;
        };
    };
};

template<class args_gen>
struct compute_type {
    using type = int(*)(typename args_gen::type1, typename args_gen::type2);
};

void foo() {
    using int_matrix_gen = VArg<int, Matrix>;
    {
        using args_ab = int_matrix_gen::arg1<1>::arg2<2,3>;
        compute_type<args_ab>::type cptr = compute;
        cptr(a, b);
        //cptr(c, d); This wont compile
    }
    {
        using args_cd = int_matrix_gen::arg1<1,2>::arg2<3>;
        compute_type<args_cd>::type cptr = compute;
        cptr(c, d);
        //cptr(a, b); This wont compile
    }

}
模板
结构矩阵{};
基质a;矩阵b;
矩阵c;矩阵d;
模板
自动计算(矩阵,矩阵){返回0;}
模板
结构变量{
模板
结构arg1{
使用类型=MatType;
模板
结构arg2{
使用类型1=类型;
使用type2=MatType;
};
};
};
模板
结构计算类型{
使用type=int(*)(typename args_gen::type1,typename args_gen::type2);
};
void foo(){
使用int_矩阵_gen=VArg;
{
使用args_ab=int_matrix_gen::arg1::arg2;

使用3个矩阵参数计算类型支持函数。

它们显然不同,因为采用参数类型
Matrix
Matrix
的函数与采用参数类型
Matrix
Matrix
的函数不同。在这种情况下,当我进行自动fp=&compute时nstance被实例化,因为编译器没有将该行标记为错误?难道编译器不应该抱怨吗?我相信如果你编写
compute
,它会将所有三个参数赋给
U1
,并将
U2
保留为空,但是IIRC,当涉及到像这样的问题时,标准文本很难理解s、 不要这样做。非常感谢Brian。有人刚刚把我指给gcc.godbolt.org。我把整个代码粘贴在那里,并排显示的程序集清楚地指出了实例。如果我以前知道的话,我会使用它,也不必问这个问题。这是为其他没有使用过该网站的人准备的JFYI。谢谢很多,巴里。
auto fp1 = get_computer<std::integer_sequence<int, 1>, std::integer_sequence<int, 2, 3>>{}();
auto fp2 = get_computer<std::integer_sequence<int, 1, 2>, std::integer_sequence<int, 3>>{}();
template<int... V1>
struct Mat1 {
    template<int... V2>
    struct Mat2 {
        using compute_type = int(*)(Matrix<V1...>, Matrix<V2...>);
    };
};

void foo() {
    {
        using compute_type = Mat1<1>::Mat2<2,3>::compute_type;
        compute_type ct = compute;
        ct(a, b);
        //ct(c, d); //This wont compile
    }
    {
        using compute_type = Mat1<1,2>::Mat2<3>::compute_type;
        compute_type ct = compute;
        ct(c, d);
        //ct(a, b);  //This wont compile
    }
}
template<int... Us>
struct Matrix{};

Matrix<1> a; Matrix<2,3> b;
Matrix<1,2> c; Matrix<3> d;

template<int... U1, int... U2>
auto compute(Matrix<U1...>, Matrix<U2...>){return 0;}

template<class Scalar, template<Scalar...> class MatType>
struct VArg {
    template<Scalar... V1>
    struct arg1 {
        using type = MatType<V1...>;
        template<Scalar... V2>
        struct arg2 {
            using type1 = type;
            using type2 = MatType<V2...>;
        };
    };
};

template<class args_gen>
struct compute_type {
    using type = int(*)(typename args_gen::type1, typename args_gen::type2);
};

void foo() {
    using int_matrix_gen = VArg<int, Matrix>;
    {
        using args_ab = int_matrix_gen::arg1<1>::arg2<2,3>;
        compute_type<args_ab>::type cptr = compute;
        cptr(a, b);
        //cptr(c, d); This wont compile
    }
    {
        using args_cd = int_matrix_gen::arg1<1,2>::arg2<3>;
        compute_type<args_cd>::type cptr = compute;
        cptr(c, d);
        //cptr(a, b); This wont compile
    }

}