c – 函数模板声明顺序影响可见性(有时)

我正在尝试创建一个函数:

template <typename T>
void doIt( T*& p )
{
   if ( !p ) { return; }
   T& ref = *p;
   getClassName( ref );
}

其中行为根据传入的p的类型而变化.特别是,调用的getClassName版本应该取决于p的类型.在以下示例中,我可以成功调用:

doIt<myClass1>( myClass1*& )
doIt<myClass1<int> >( myClass1*& )
doIt<myClass2>( myClass2*& )
doIt<myClass2<int> >( myClass2*& )

但是当我打电话时它失败了:

doIt< std::vector<int, std::allocator<int> > >( std::vector<int, std::allocator<int>>*& )

有错误:

a.cxx: In function ‘void doIt(T*&) [with T = std::vector<int, std::allocator<int> >]’:
ba.cxx:87:   instantiated from here
a.cxx:33: error: invalid initialization of reference of type ‘MyClass1&’ from expression of type ‘std::vector<int, std::allocator<int> >’
a.cxx:16: error: in passing argument 1 of ‘const char* getClassName(MyClass1&)’

(gcc 4.2.4).

如果我移动声明:

template<typename T, typename A>
char const* getClassName( std::vector<T,A>& ) { printf("std::vector<T,A>\n"); return NULL; }

在它之前 – 然后它编译.所以,

>为什么要在doIt之前出现getClassName(std :: vector< T,A>&)而不是getClassName(MyClass2T< T>&)
>我能做些什么来独立于std :: vector? (我希望能够将doIt放在自己的头文件中,而不必了解std :: vector或任何特殊化,这将是用户定义的).

.

#include <stdio.h>
#include <assert.h>
#include <vector>

//template<typename T>
//char const* getClassName( T& );

//template<typename T, typename A>
////char const* getClassName( std::vector<T,A>& ) { printf("std::vector<T,A>\n"); return NULL; }

#if 1
// ---------  MyClass2
struct MyClass1
{};

char const* getClassName( MyClass1& ) { printf("MyClass1\n"); return NULL; }

// ---------  MyClass1T
template< typename T>
struct MyClass1T
{};

template<typename T>
char const* getClassName( MyClass1T<T>& ) { printf("MyClass1T<T>\n"); return NULL; }
#endif


template <typename T>
void doIt( T*& p )
{
   if ( !p ) { return; }
   T& ref = *p;
   getClassName( ref );
}


// ---------  MyClass2
struct MyClass2
{};


// declared after doIt, OK.
char const* getClassName( MyClass2& ) { printf("MyClass2\n"); return NULL; }

// ---------  MyClass2T
template< typename T>
struct MyClass2T
{};

// declared after doIt, OK.
template<typename T>
char const* getClassName( MyClass2T<T>& ) { printf("MyClass2T<T>\n"); return NULL; }

template<typename T, typename A>
char const* getClassName( std::vector<T,A>& ) { printf("std::vector<T,A>\n"); return NULL; }



void test()
{
#if 1
   MyClass1 mc1;
   MyClass1* mc1p = &mc1;
   doIt( mc1p );

   MyClass2 mc2;
   MyClass2* mc2p = &mc2;
   doIt( mc2p );

   MyClass1T<int> mc1t;
   MyClass1T<int>* mc1tp = &mc1t;
   doIt( mc1tp );

   MyClass2T<int> mc2t;
   MyClass2T<int>* mc2tp = &mc2t;
   doIt( mc2tp );

   // Nested templates are OK.
   MyClass2T<MyClass1> mc2t2;
   MyClass2T<MyClass1>* mc2tp2 = &mc2t2;
   doIt( mc2tp2 );
#endif

#if 1
   std::vector<int> v;
   std::vector<int>* vp = &v;
   doIt( vp );                   // FAIL!
#endif
}

解决方法:

Why is it required that getClassName( std::vector& ) appear before doIt but not getClassName( MyClass2T& )

任何函数都需要声明范围.使用向量< int>实例化模板函数时它期望一个带有签名getClassName(vector< int>&)的函数出现(至少是一个原型),以便编译成功.

What can I do do make doIt independent of std::vector? (I want to be able to place doIt in its own header and not have to know about std::vector, or any of the specializations, which will be user-defined)

阅读FAQ on Templates.在第一次实例化doIt之前,尝试放置所有doIt依赖模板函数的原型.

上一篇:使用Java进行小数据集的数据查找方法?


下一篇:Python中函数查找操作的时间复杂度是多少