我有以下包装器制造商metametafunction:
template <class ToWrap>
struct wrapper_maker
{
template <bool>
struct wrapper
{
wrapper(ToWrap& a) : a(a) { }
ToWrap& a;
};
};
我想在此模板函数foo
中使用它:
template <class ToWrap>
void foo(typename wrapper_maker<ToWrap>::template wrapper<true>& wrapped)
{
cout << "foo" << endl;
}
注意:用例是foo
已存在且具有不同的重载,但如果对象是wrapper_maker<ToWrap>::wrapper<bool>
实例,我希望调用此特定的重载。
但是,当我编写一个用这样的对象调用foo
的函数时:
template <class ToWrap>
void call_foo(ToWrap& o)
{
typedef typename wrapper_maker<ToWrap>::template wrapper<true> wrapped_t;
wrapped_t wrapped(o);
foo(wrapped);
}
使用它:
int to_wrap = 5;
call_foo(to_wrap);
我收到此错误:
prog.cpp: In instantiation of 'void call_foo(ToWrap&) [with ToWrap = int]':
prog.cpp:32:18: required from here
prog.cpp:27:16: error: no matching function for call to 'foo(wrapped_t&)'
foo(wrapped);
^
prog.cpp:27:16: note: candidate is:
prog.cpp:17:6: note: template<class ToWrap> void foo(typename wrapper_maker<ToWrap>::wrapper<true>&)
void foo(typename wrapper_maker<ToWrap>::template wrapper<true>& wrapped)
^
prog.cpp:17:6: note: template argument deduction/substitution failed:
prog.cpp:27:16: note: couldn't deduce template parameter 'ToWrap'
foo(wrapped);
为什么?
编辑:此外,是否有任何方法可以定义foo
的特殊化,可以针对任何可能的wrapper_maker<T>::wrapper<W>
调用T
的实例,而无需指定任何T
W
在呼叫站点1}}或Sub ExpirationYeartoColors()
Dim num As Integer, lr As Long, r As Long
?
答案 0 :(得分:3)
此:
template <class ToWrap>
void foo(typename wrapper_maker<ToWrap>::template wrapper<true>& wrapped)
是非推断的上下文。具体来说,列表中的第一个来自[temp.deduct.type] 4/5:
如果模板参数仅在非推导中使用 上下文并没有明确指定,模板参数推断失败。
未推断的背景是:
(5.1) - 使用 qualified-id 指定的类型的嵌套名称说明符。
您需要明确传入ToWrap
才能使其发挥作用。
让我举一个例子,说明为什么会这样。假设我们有:
template <typename T> struct some_fn;
template <> struct some_fn<A> { using type = int; };
template <> struct some_fn<B> { using type = int; };
template <typename T>
void foo (typename some_fn<T>::type);
foo(0); // what should T be?
通常,为了实现这一点,编译器必须知道some_fn
的每个可能的特化 - 即使some_fn<T>::type
只有int
wrapper_maker<T>::wrapper<W>
。
此外,有没有办法定义foo的特化,可以在
T
的实例上调用任何可能的T
,而不必指定W
或{{ 1}}在呼叫现场?
总的来说,不,出于上述相同的原因。但是,您只需向wrapper
添加其他信息:
template <class ToWrap>
struct wrapper_maker
{
template <bool b>
struct wrapper
{
static constexpr bool value = b;
using to_wrap = ToWrap;
// etc.
};
};
template <typename WrapperT>
void foo(WrapperT& wrapped) {
// typename WrapperT::to_wrap is your T
// WrappedT::value is your W
}