C ++ 11模板函数接受多个模板别名

时间:2014-05-12 14:13:18

标签: c++ templates c++11

我想创建一个接受多个模板别名的模板函数。 这是一个更有意义的简单例子。

有模板别名 TAlias1和TAlias2

template <typename T>
using TAlias1 = TClass1<T, 2>;

template <typename T>
using TAlias2 = TClass2<T, 3>;

...然后我想创建一个接受上述任何别名的模板函数:

template <typename T, template<typename> class TClass>
TClass<T> someOperation(const TClass<T> &a, const TClass<T> &b)
{
   ...
}

int main()
{
   TAlias1<float> a;
   TAlias1<float> b;

   TAlias1<float> c = someOperation(a,b);

   return 0;
}

但是,它会导致Visual Studio 2013中的编译错误:

这种情况有解决办法吗?

修改

以下是产生错误的完整示例:

template <typename T, int I>
struct TClass1 {};

template <typename T, int I>
struct TClass2 {};

template <typename T>
using TAlias1 = TClass1<T, 2>;

template <typename T>
using TAlias2 = TClass2<T, 3>;

// this should accept TAlias1 and TAlias2
template <typename T, template<typename> class TClass>
TClass<T> someOperation(const TClass<T> &a, const TClass<T> &b) { return {}; }

int main()
{
    TAlias1<float> a;
    TAlias1<float> b;
    TAlias1<float> c = someOperation(a,b);

    TAlias2<float> d;
    TAlias2<float> e;
    TAlias2<float> f = someOperation(d,e);

   return 0;
}

错误:

error C2784: 'TClass<T> someOperation(const TClass<T> &,const TClass<T> &)' : could not deduce template argument for 'const TClass<T> &' from 'TClass1<float,2>'

3 个答案:

答案 0 :(得分:1)

这是错误的:

template <typename T, template<typename> class TClass>
TClass<T> someOperation(const TClass<T> &a, const TClass<T> &b)

如果没有以任何方式提供I参数,编译器将如何解析?你需要做的是:

template <typename T, int I>
TClass<T, I> someOperation(const TClass<T, I> &a, const TClass<T, I> &b)

此功能适用于每个TClass具体化。以下是您完整的工作示例:

template <typename T, int I>
struct TClass
{
public:
    T value;

    TClass<T,I> operator+(const TClass<T,I> &b) const
    {  
       TClass<T, I> result;
       result.value = value + b.value;
       return result;
    }

    int getI()
    {
        return I;
    }
};

template <typename T>
using TAlias1 = TClass<T, 2>;

template <typename T>
using TAlias2 = TClass<T, 3>;

// this should accept TAlias1 and TAlias2
template <typename T, int I>
TClass<T, I> someOperation(const TClass<T, I> &a, const TClass<T, I> &b)
{
    return a+b;
}

int main()
{
    TAlias1<float> a;
    TAlias1<float> b;
    TAlias1<float> c = someOperation(a,b);

   return 0;
}

OP的评论后,

编辑。别名只是一个别名,而不是一个不同的类。该函数将接受所有TClass个对象。您只能通过为每个别名创建部分专用函数来限制它:

template<typename T>
TAlias1<T> foo(TAlias1<T> a, TAlias1<T> b)

答案 1 :(得分:1)

我认为你想做的事情无法完成。

这应该有效:

TAlias1<float> c = someOperation<float, TAlias1>(a,b);

但是自动模板扣除失败,因为ab实际上是TClass<float,2>类型,并且与预期的模板参数不匹配。

是的,它们被声明为TAlias1<float,它与预期的模板参数匹配,但是别名就是别名,它不是变量的真实类型,也不用于模板扣除

您可以尝试一些解决方法,例如:

template <typename T>
struct TAlias1 : TClass<T, 2> {};

但是你可能会遇到一些类型问题......

当然,您可以使用TClass参数覆盖模板函数。其实我不确定你为什么不首先这样做......

答案 2 :(得分:1)

问题出在someOperation函数的第二个模板参数中。模板别名不会引入新类型,它的工作方式类似于typedef。这意味着,即使TAlias1只接受一个模板参数,它仍然是一个带有2个参数的模板(其中设置了第二个参数)。

事实上,如果你将功能更改为:

template <typename T, template<typename,int> class TClass>
TClass<T,2> someOperation(const TClass<T,2> &a, const TClass<T,2> &b)
{
    return a+b;
}

它将编译(当然,你需要使operator+ const方法)。

更好的方法是不要将模板类用作第二个模板参数,并将函数更改为以下内容:

template <typename T1, typename T2>
auto someOperation(const T1 &a, const T2 &b) -> decltype(a+b)
{
    return a+b;
}

或者甚至可能:

template <typename T>
T someOperation(const T &a, const T &b)
{
    return a+b;
}