4

我遇到了一个 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

4

3 回答 3

4

您正在尝试部分专门化成员函数模板。这是不可能的,我怕...

于 2013-03-08T19:50:29.370 回答
4

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

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);

这设置SB2<int>并且函数需要一个参数S x- 但整数5不能转换为该类型。将其更改为:

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

它也有效。

请注意,这可能无法解决您试图解决的问题,它只是解释了会发生什么。


考虑您的编辑:我认为您尝试专门化的事实T=std::tuple<...>已经指明了方向:T是模板参数,A就是您应该专门化的内容。也许是这样的:

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...
};
于 2013-03-08T20:07:31.680 回答
1

如果要将另一个模板传递给模板,则必须使用模板模板参数,因此您的 A<> 模板如下所示:

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

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

如果您的原始模板没有采用这种参数类型,我认为您不能专注于模板模板参数。

于 2013-03-08T19:46:29.527 回答