0

我是 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(if_::value,const T&,T>::type)”:无法推断“T”的模板参数

也许这是错误的处理方式。如果可能的话,我会尝试减少为相同功能编写的相对重复模板的数量。

4

3 回答 3

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());
}

另一种选择将涉及包装函数和类模板。无论哪种方式,尽管外部功能都必须是 ref。

于 2013-03-15T23:34:06.287 回答
1

您正在尝试T非推断上下文推断类型。

参数的依赖类型中出现双冒号通常会提示您无法推断出该参数的类型(除非您在同一个函数调用中有其他推断的上下文有帮助,但这里只有一个争论)。

来自 C++11 标准的第 14.8.2.5/5 段:

未推断的上下文是:

— 使用限定 ID 指定的类型的嵌套名称说明符。

[...]

如果你需要一个具体的例子,这个 StackOverflow 上的问答提供了一个很好的例子。在这种情况下,您可以显式提供类型参数:

myfunc<Byref<int>>(arg);

或者,您可以选择第二个问答中提出的两种解决方法之一。

于 2013-03-15T23:34:56.490 回答
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
}
于 2013-03-15T23:48:21.460 回答