请考虑以下代码:
template < typename T >
struct A
{
struct B { };
};
template < typename T >
void f( typename A<T>::B ) { }
int main()
{
A<int>::B x;
f( x ); // fails for gcc-4.1.2
f<int>( x ); // passes
return 0;
}
所以这里gcc-4.1.2要求明确指定f
的模板参数。这符合标准吗?较新版本的GCC是否修复了此问题?如何在调用int
时明确指定f
?
更新 这是一种解决方法。
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
template < typename T >
struct A
{
typedef T argument;
struct B { typedef A outer; };
};
template < typename T >
void f( typename A<T>::B ) { }
template < typename Nested >
void g( Nested )
{
typedef typename Nested::outer::argument TT;
BOOST_STATIC_ASSERT( (boost::is_same< typename A<TT>::B, Nested >::value) );
}
struct NN
{
typedef NN outer;
typedef NN argument;
};
int main()
{
A<int>::B x;
NN y;
g( x ); // Passes
g( y ); // Fails as it should, note that this will pass if we remove the type check
f( x ); // Fails as before
return 0;
}
但是,我仍然无法理解为什么呼叫f( x );
无效。你能否参考标准中的某些观点,说这种呼叫应该是无效的?你能举出一个这样的电话不明确的例子吗?
答案 0 :(得分:10)
typename A<T>::B
这里,T
处于非弱化上下文中,这意味着无法从函数参数中推导出T
。
问题在于,在一般情况下,可能有无数种可能匹配的T
类型。例如,考虑是否struct B { };
代替typedef int B;
。
答案 1 :(得分:4)
如何在调用f?
时避免显式指定int
只需让B
声明其嵌套类类型
template < typename T >
struct A
{
struct B { typedef A outer; };
};
然后你可以推断它。以下是外部模板,内部的typedef和返回类型
template<template<typename> class Outer, typename D, typename R = void >
struct nesting { };
template<template<typename> class Outer, typename Arg, typename R>
struct nesting< Outer, Outer<Arg>, R > {
typedef Arg arg1_type;
typedef R type;
};
template < typename T >
typename nesting<A, typename T::outer>::type
f(T) {
/* nesting<A, typename T::outer>::arg1_type is A's T */
}
答案 2 :(得分:0)
如何避免明确指定 int调用f?
您需要struct B
的一些帮助。
template < typename T >
struct A
{
struct B
{
static T getType(); // no impl required
};
};
#define mytypeof(T) (true?0:T)
template < typename T, typename U >
void f( T t, U ) { } // U will be T of A<T>::B
使用以下内容进行调用:
f(x, mytypeof(x.getType()));
或者,您可以通过引入另一个f调用函数来抽象mytypeof(x.getType())
,这样您就可以拥有原始f(x)
。 e.g。
template < typename T, typename U >
void b( T t, U ) { } // U will be T of A<T>::B
template < typename T >
void f( T t )
{
b(t, mytypeof(t));
}
然后,您可以致电f(x)
。
答案 3 :(得分:0)
跟进“更新”中的问题,这里的情况是f
的调用不明确(如果允许的话):
// Definitions of generic "struct A", as well as "f()", are the same as above
// But additionally, consider a specialized "struct A", defined as follows:
template <>
struct A<double>
{
typedef A<int>::B B;
}
// Now consider the call to "f", similarly to before:
int main()
{
// Possibility 1 for argument to "f()"
// A<int>::B x;
// Possibility 2 for argument to "f()": Use the specialized version of "struct A"
A<double>::B x;
f(x); // which value to deduce for type T? Could be "int" or "double"
}
注意一组模糊的潜在实例化函数f
:f<int>()
和f<double>
都会成功调用f()
。