模板难题

时间:2013-03-08 19:42:24

标签: c++ templates c++11 template-specialization

我遇到了一个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中的类型仍未绑定。

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分: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);

这将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...
};

答案 2 :(得分:1)

如果您想将另一个模板传递给模板,则必须使用template template parameters,因此您的A&lt;&gt;模板看起来像这样:

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

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

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