【问题标题】:C++ using function template in class templateC++ 在类模板中使用函数模板
【发布时间】:2014-01-29 02:29:59
【问题描述】:
template <int C> class MyClass;

...     


template <int C>
double trans(MyClass<C> &a)
{
    //return some double 
}

//this is supposed to be function template
template <int C>
double func(MyClass<2> &a)
{
    //return some double
}

template <int C>
MyClass<C-1> func(MyClass<C> &a)
{
    MyClass<C-1> ret;
    return ret;
}

template <int C>
double otherFunc(MyClass<C> &a)
{
     double result;
     if(C == SOME_CONSTANT)
         result = func(a);
     else
         result = trans(func(a));

}

我的问题是我想检查参数otherFunc调用函数模板func(返回双精度)中的模板参数C,而不是类模板func(返回MyClass)的成员函数。但不知何故,编译器试图 func 返回 MyClass in

     if(C == SOME_CONSTANT)
         result = func(a);

这部分所以我得到了编译器错误(因为 double = MyClass 不可行)。我该如何解决这个问题?

【问题讨论】:

  • otherFunc 需要合法才能编译 C 的值,它被实例化 - 包括 if/else 语句中的分支永远不能为C 的值取值。换句话说,即使SOME_CONSTANT2,当C 不是2 时,它仍然会检查result = func(a) 代码的合法性——导致您看到的转换错误。怎么修? - 你可以避免if/else,方法是为C != 2 提供一个通用的otherFunc 模板和一个2 的专业化模板。不过,目前还不是很清楚你真正想要达到的目标......
  • 我只是想让 func 在 C == 2 时的行为与其他行为略有不同。如果您能详细说明一下,我将不胜感激

标签: c++ templates


【解决方案1】:

很难在评论中详细说明,所以我会发布一个答案。回顾一下我在 cmets 中所说的话:

  • if/else 中的 otherFunc 不能为特定的 MyClass 实例化编译是不合法的,
  • 可以使用相同的模板专业化方法来创建替代的otherFunc 定义来处理MyClass&lt;2&gt;s。

示例代码:

#include <iostream>

template <int C>
class MyClass
{ };

template <int C>
double trans(const MyClass<C> &a)
{
    return C + 700;
}

template <int C>
MyClass<C-1> func(MyClass<C> &a)
{
    MyClass<C-1> ret;
    return ret;
}


double func(MyClass<2>& a)
{
    return 200.0;
}

template <int C>
double otherFunc(MyClass<C> &a)
{
     return trans(func<C>(a));
}

template <>
double otherFunc<2>(MyClass<2>& a)
{
    return func(a);
}


int main()
{
    MyClass<2> a;
    std::cout << otherFunc(a) << '\n';

    MyClass<4> b;
    std::cout << otherFunc(b) << '\n';
}

输出:

200
703

【讨论】:

  • 谢谢,我还在努力学习 C++ 中的模板:/ 我不太明白专业化的概念
  • @REALFREE:语法需要一些时间来适应 ;-)。
  • 哦,顺便说一句,我还有一个问题,所以你从双函数(MyClass& a)中删除模板,这仍然是一个类模板函数吗?
  • @REALFREE: 否 - 我已经用另一个专用于 MyClass&lt;2&gt;s 参数的非模板函数“重载”模板。这对于具有不同的返回类型是必要的。
【解决方案2】:

我猜原因是:

 if(C == SOME_CONSTANT)
     result = func(a);
 else
     result = trans(func(a));

在运行时检查,而模板特化和类型检查在编译期间完成。这两个功能:

 template <int C>
 double func(MyClass<2> &a)
 {
     //return some double
 }

 template <int C>
 MyClass<C-1> func(MyClass<C> &a)
 {
     MyClass<C-1> ret;
     return ret;
 }

具有几乎相同的签名 - 唯一的区别是 C==2 使用返回 double 的签名,否则使用返回 MyClass&lt;2&gt; 的签名。所以你得到的是:

 // for C==2
 if(C == SOME_CONSTANT)
     result = func<2>(a); // returns double - just like you wanted
 else
     result = trans<2>(func<2>(a)); // pass double into trans<?>(MyClass<?>), so the parameter cannot be resolved unless you specified some implicit constructor/explicit conversion operator 

 // for e.g. C==3
 if(C == SOME_CONSTANT)
     result = func<3>(a); // returns MyClass<2> while result is double
 else
     result = trans<2>(func<3>(a)); // pass MyClass<2> into trans<?>(MyClass<>) - like you wanted

所以基本上你的代码在第一种或第二种情况下的特化类型无效。你可以这样做:

 template <>
 MyClass<2> func<2>(MyClass<2> &a)
 {
     return a;
 }

 template <int C>
 MyClass<C-1> func(MyClass<C> &a)
 {
     return MyClass<C-1>;
 }

保持模板类型一致,然后:

if(C == SOME_CONSTANT)
   result = trans(a);
else
   result = trans(func(a));

这只是一个如何处理它的示例。如果您避免为不同的模板专业化输入不同的返回类型,事情应该会更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    相关资源
    最近更新 更多