模板的难题

Template Conundrum

本文关键字:难题      更新时间:2023-10-16

我遇到了一个c++模板难题。我试着把它削减到最低限度,现在我甚至不确定我想做的是否可能。看一下下面的代码(在某个.h文件中):

template<typename T>
class A
{
public:
    template<typename S>
    void f(S x);
};
class B1 { };
template<typename S>
class B2 { };
//This one works:
template<>
template<typename S>
void A<B1>::f(S x)
{
}    
//This one does not work:
template<>
template<typename S>
void A<B2<S>>::f(S x)
{
}

在我的main函数中我有这样的东西:

//This one works:
A<B1> first;
first.f<int>(5);
//This one does not work:
A<B2<int>> second;
second.f<int>(5);

我得到的错误信息是因为第二部分是

error C3860: template argument list following class
             template name must list parameters in the
             order used in template parameter list
error C3855: 'A<T>': template parameter 'T' is
             incompatible with the declaration

你知道是什么问题吗?


<标题>编辑

为了使问题更具体,下面是我的动机。我希望上面的函数f具有T=std::tuple<T1, T2>, T=std::tuple<T1, T2, T3>T=std::tuple<T1, T2, T3, T4>的专门化,其中tuple中的类型仍然未绑定。

您正在尝试部分特化成员函数模板。这恐怕是不可能的。

您的代码有两个问题。首先,第二个专门化是非法的,因为

template<> // parameters useable for the specialization of A you refer to
           // since it is a function, no partial specialization is allowed.
template<typename S> // parameters for the function's parameters
void A<B2<S>>          // S can not be used here!
             ::f(S x)  // only here
{
}

如果我把它改成

template<>
template<typename S>
void A<B2<int>>::f(S x)
{
}

它工作了,现在第二个问题暴露了:

second.f<B2<int>>(5);

S设置为B2<int>,并且该函数需要参数S x,但是不能将整数5转换为该类型。改为:

B2<int> x;
second.f<B2<int>>(x);

,它也可以工作。

注意,这可能不能解决你试图解决的问题,它只是解释发生了什么。


关于你的编辑:我认为你试图为T=std::tuple<...>专门化的事实已经指明了方向:TA的模板参数,是你应该专门化的。比如:

template< typename T >
class F // used to implement f(), so you can specialize
        // just F/f() instead of the whole class A
{
  void f(T x) { /* default impl */ }
};
template< typename T1, typename T2 >
class F< std::tuple< T1, T2 > >
{
  void f(T1 x, T2 y) { /* special impl */ }
};
template< typename T >
class A : public F< T >
{
    // ...other stuff...
};

如果你想传递另一个模板给一个模板,你必须使用模板模板参数,所以你的A<>模板看起来像这样:

template<typename T>
class A
{
public:
    template<template <typename> class H, typename S>
    void f(H<S> x);
};

现在你可以将模板传递给你的模板了。

我不认为你可以专门化模板模板参数,如果你的原始模板没有这样的参数类型。