15

考虑以下代码:

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 );无效。您能否参考标准中的某些点,即此类调用应该是无效的?你能举一个这样的电话模棱两可的例子吗?

4

4 回答 4

12
typename A<T>::B

在这里,T是在非推导的上下文中,这意味着T不能从函数参数中推导出来。

问题在于,在一般情况下,可能有无数种可能的类型T可以匹配。例如,考虑一下,如果不是struct B { };你有typedef int B;.

于 2010-11-03T22:30:54.183 回答
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 */ 
}
于 2010-11-05T13:31:10.157 回答
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().

于 2013-12-30T15:54:08.957 回答
0

如何避免在调用 f 时显式指定 int?

你需要一点帮助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). 例如

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).

于 2010-11-03T23:24:39.837 回答