2010-11-03 162 views
12

考慮下面的代碼:C++:嵌套類模板類

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是否解決了這個問題?我如何避免在撥打f時明確指定int

更新: 這是一種解決方法。

#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);是無效的。你能否在標準中提到這種呼叫應該是無效的一點?你能舉出一個這樣的電話不明確的例子嗎?

回答

10
typename A<T>::B 

這裏,T處於nondeduced上下文中,這意味着T不能從函數參數來推斷。

的問題是,在一般情況下,存在可能類型T可能匹配的可能無限數量。舉個例子,如果不是struct B { };你有typedef int B;

+2

感謝您的回答。爲什麼'T'不能從函數參數中推導出來?你能舉一個例子來說明'T'有兩種類型,它們與'f'的特定調用相匹配嗎?你的意思是,對於'A'的另一個專門化,它可能是另一個'typedef int B;'而不是'struct B {};'?我看不出爲什麼在這種情況下'f'的調用應該是不明確的。 – Vahagn 2010-11-04 07:58:01

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)

+1

感謝您的回答。添加一個額外的參數對我不起作用,因爲實際上我已經覆蓋了操作符而不是'f'。 – Vahagn 2010-11-04 08:01:25

4

我怎樣才能避免明確指定INT同時呼籲F·

只是要B聲明其嵌套類類型

template < typename T > 
struct A 
{ 
    struct B { typedef A outer; }; 
}; 

然後你就可以推斷出結論。下面以外部模板,內部的類型定義和返回類型

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 */ 
} 
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()