C++: nested class of a template class

后端 未结 4 2078
被撕碎了的回忆
被撕碎了的回忆 2020-12-10 13:09

Consider the following code:

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

template < typename T >
void f( typename A::B ) {          


        
相关标签:
4条回答
  • 2020-12-10 13:24

    How can I avoid explicitly specifying int while calling f?

    Just make B declare its nesting class type

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

    Then you can deduce it. The following takes the outer template, the inner's typedef and a return type

    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 讨论(0)
  • 2020-12-10 13:26

    How can I avoid explicitly specifying int while calling f?

    You'll need a little help from 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
    

    Calling it with the following:

    f(x, mytypeof(x.getType()));
    

    Alternatively, you could abstract mytypeof(x.getType()) away by introducing another function which f calls, so you could have your original 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));
    }
    

    You could then call f(x).

    0 讨论(0)
  • 2020-12-10 13:47
    typename A<T>::B
    

    Here, T is in a nondeduced context, which means that T cannot be deduced from the function argument.

    The problem is that in the general case, there is a potentially infinite number of possible types T that could match. Consider, for example, if instead of struct B { }; you had typedef int B;.

    0 讨论(0)
  • 2020-12-10 13:50

    Following up on the question in the "Update", here is a situation in which the call to f would be ambiguous (if it were allowed, that is):

    // 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"
    }
    

    Notice the ambiguous pair of potential instantiated functions f: Both f<int>() and f<double> would result in a successfull call to f().

    0 讨论(0)
提交回复
热议问题