1

此代码将失败并显示错误消息(行号已关闭)。我该如何解决这个问题(保持相同的意图)?

g++ -o c_test c_test.cpp

c_test.cpp:在函数'int main(int,char**)'中:

c_test.cpp:28:18: 错误: 没有匹配函数调用'wcalc(CWrapped<5>::u_type&)'

c_test.cpp:28:18: 注意:候选人是:

c_test.cpp:17:58: 注意:模板 int wcalc(typename CWrapped::u_type)

包装的类型被传递给“calc”和“wcalc”函数,但第二个失败了。我希望能够包装类型,以便我可以使用编译时定义来指定不同的类型,但仍然使用相同的包装函数

// Example template class
template <int T_B>
class m_int {
public:
  int x;
  m_int() { x = T_B; }
  int to_int() { return(x); }
};

// Desired Typedef wrap
template <int T_BITS> struct CWrapped {
  typedef m_int<T_BITS> u_type;
};


// This is ok, no wrapping
template <int T_BITS> int calc(m_int<T_BITS> x) {
  return(x.to_int());
}
// This fails when instantiated
template <int T> int wcalc(typename CWrapped<T>::u_type x) {
  return(x.to_int());
}


int main(int argc, char* argv[]) {
  CWrapped<5>::u_type s;

  int x = calc(s);
  int y = wcalc(s);
  return(0);
}
4

2 回答 2

3

来自 C++11 标准,第 14.8.2.5/16 段

“如果在声明具有非类型模板参数的函数模板中,在函数参数列表中的子表达式中使用了非类型模板参数,则该表达式是如上所述的非推导上下文。示例:”

template <int i> class A { / ... / };
template <int i> void g(A<i+1>);
template <int i> void f(A<i>, A<i+1>);
void k() {
    A<1> a1;
    A<2> a2;
    g(a1); // error: deduction fails for expression i+1
    g<0>(a1); // OK
    f(a1, a2); // OK
}

“注意:如果模板参数仅在非推导上下文中使用,则不参与模板实参推导。例如:”

template<int i, typename T> 
T deduce(typename A<T>::X x, // T is not deduced hereT t, // but T is deduced here
typename B<i>::Y y); // i is not deduced here
A<int> a;
B<77> b;
int x = deduce<77>(a.xm, 62, b.ym);
// T is deduced to be int, a.xm must be convertible to
// A<int>::X
// i is explicitly specified to be 77, b.ym must be convertible
// to B<77>::Y

T由于上述原因,无法推断出您的非类型模板参数:您必须明确提供它:

int main(int argc, char* argv[]) {
  CWrapped<5>::u_type s;

  int x = calc(s);
  int y = wcalc<5>(s); // Template argument 5 cannot be deduced!
  return(0);
}

另请参阅此相关链接:C++,模板参数无法推断(@NateKohl 提供)

于 2013-01-08T22:27:57.550 回答
0

您的问题是,这是从依赖上下文中的CWrapped映射。intu_type

您需要一个从u_type到的映射int才能进行类型推导。

模板类型推导是简单的模式匹配,它不会反转任意模板结构。

例如,以下是如何提取CWrapped将解析为T

template<typename T>
struct GetWrapped;

template<int N>
struct GetWrapped< m_int<N> > {
  typedef CWrapped< N > type;
};

template <int T> int wcalc(T const& x) {
  typedef typename GetWrapped<T>::type CWrappedType; // assuming you need it for something
  return(x.to_int());
}

以下是您只能接受T在重载决议中有这样一个映射的方式:

#include <type_traits>
template <int T> auto wcalc(T const& x)->typename std::enable_if< sizeof(typename GetWrapped<T>::type), int>::type  {
  return(x.to_int());
}

它使用 SFINAE 和 C++11 特性来检查这GetWrapped<T>是一个有效的构造。

现在,这可能是一个 XY 问题,就像您问过 X 一样,但您确实需要知道 Y。我希望上述其中一项会有所帮助。

于 2013-01-09T14:31:58.600 回答