我是c ++模板的新手。我正在编写一组可以操作两个不同模板类的函数。需要始终按值传递,另一个必须通过引用传递,因为它代表了大量数据。
这是一个简化的例子。如果arg被标记为ref类型,我希望将函数签名定义为通过const ref获取它。
template<bool B, typename, typename T2>
struct if_ {};
template<typename T1, typename T2>
struct if_<true, T1, T2> {
typedef T1 type;
};
template<typename T1, typename T2>
struct if_<false, T1, T2> {
typedef T2 type;
};
struct ByvalTypeTag {};
template<typename T>
class Byval : public ByvalTypeTag
{
T somedata;
};
struct ByrefTypeTag {};
template<typename T>
class Byref : public ByrefTypeTag
{
T somedata;
};
template<typename T>
void myfunc(typename if_<std::is_base_of<ByrefTypeTag, T>::value, const T&, T>::type arg)
{
}
int _tmain(int argc, _TCHAR* argv[])
{
Byref<int> arg;
myfunc( arg );
return 0;
}
我得到的错误是:
错误C2783:'void myfunc(如果_ :: value,const T&amp;,T&gt; :: type)':无法推断'T'的模板参数
这可能是错误的做法。如果可能的话,我正在努力减少我为同一个函数编写的相对重复模板的数量。
答案 0 :(得分:1)
是的,编译器无法推断出类型。你需要自己提供T:
myfunc<ByRef<int>>(arg);
或者,您可以使用更常见的标签调度系统:
class byref
{
typedef byref_tag tag;
...
};
template < typename T >
void fun(T const& t, byref_tag) { ... }
template < typename T >
void fun(T t, byval_tag) { ... }
template < typename T >
void fun(T const& t)
{
typedef typename T::tag tag;
fun(t,tag());
}
另一种替代方案是涉及包装函数和类模板。无论哪种方式,外部函数必须是参考。
答案 1 :(得分:1)
您正尝试从非推断的上下文中推断出类型T
。
参数依赖类型中双重冒号的存在通常会提示您将无法推断出该参数的类型(除非您在相同的函数调用中有其他推断的上下文有帮助,但在此处只有一个论点)。
来自C ++ 11标准的第14.8.2.5/5段:
未推断的上下文是:
- 使用qualified-id。
指定的类型的嵌套名称说明符[...]
如果你需要一个具体的例子, this Q&A on StackOverflow 提供了一个非常好的例子。在这种情况下,您可以明确提供类型参数:
myfunc<Byref<int>>(arg);
或者,您可以选择this second Q&A中提议的两种解决方法之一。
答案 2 :(得分:0)
您可以使用此实现转发参数。
template<typename T>
void myfunc_impl(T arg)
{
// Do the work here.
}
template<typename T>
void myfunc(const T &arg, typename std::enable_if<std::is_base_of<ByrefTypeTag, T>::value>::type* = 0)
{
myfunc_impl<const T&>( arg ); // Pass a const ref
}
template<typename T>
void myfunc(const T &arg, typename std::enable_if<std::is_base_of<ByvalTypeTag, T>::value>::type* = 0)
{
myfunc_impl<T>( arg ); // Pass a copy
}