为什么不能推导出这个metametafunction的模板参数呢?
Why can't this metametafunction's template parameter be deduced?
我有以下 wrapper-maker 元元功能:
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
在呼叫站点?
这个:
template <class ToWrap>
void foo(typename wrapper_maker<ToWrap>::template wrapper<true>& wrapped)
是非推导上下文。具体来说,列表中的第一个来自 [temp.deduct.type]4/5:
If a template parameter is used only in non-deduced
contexts and is not explicitly specified, template argument deduction fails.
The non-deduced contexts are:
(5.1) — The nested-name-specifier of a type that was specified using a 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
。
Further, is there any way to define a specialization of foo that will get called on instances of wrapper_maker<T>::wrapper<W>
, for any possible T
, without having to specify either T
or W
at the call-site?
一般来说,不会,原因与上述相同。但是,您可以将其他信息添加到 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
}
我有以下 wrapper-maker 元元功能:
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
在呼叫站点?
这个:
template <class ToWrap>
void foo(typename wrapper_maker<ToWrap>::template wrapper<true>& wrapped)
是非推导上下文。具体来说,列表中的第一个来自 [temp.deduct.type]4/5:
If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
The non-deduced contexts are:
(5.1) — The nested-name-specifier of a type that was specified using a 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
。
Further, is there any way to define a specialization of foo that will get called on instances of
wrapper_maker<T>::wrapper<W>
, for any possibleT
, without having to specify eitherT
orW
at the call-site?
一般来说,不会,原因与上述相同。但是,您可以将其他信息添加到 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
}