如何为对象定义模板化方法,其中一些也是模板化的

时间:2015-10-16 08:19:37

标签: c++ templates

说我有:

std::multimap< std::string, netCDF_Dimension > dimensions;

和类似的多重映射。 偶尔我需要:

std::multimap< std::string, netCDF_Attribute<U> > attributes;

其中U是例如netCDF_VarAtt或netCDF_GlobalAtt。

我可以写一个搜索功能:

    template<class T>
    boost__optional<T*> Search(const std::multimap< std::string, T > currMap){
      //Search in map.
      if found
          return T*;
      else
          return boost::none
    }

这适用于标准类型/类,但不适用于netCDF_Attribute<U>。这超出了我对模板的简单理解。我需要的是:

T = netCDF_Attribute<U> 

以及明显的类型,有解决方案吗?

以下代码使用简单类型/类netCDF_Attribute<U>

进行编译

调用类的完整代码是:

template<typename U>
class netCDF_Attributes{
  std::multimap< std::string, netCDF_Attribute<U> > attributes;
public:

  boost::optional< std::pair< netCDF_Element, void * > > Find(std::vector< std::string >::const_iterator currStep, 
                                  std::vector< std::string >::const_iterator lastStep);
  void Initialise( std::multimap< std::string, U > &attMap );
};

template<typename U>
boost::optional< std::pair< netCDF_Element, void * > >  netCDF_Attributes< U >::Find(std::vector< std::string >::const_iterator currStep, 
                                             std::vector< std::string >::const_iterator lastStep){
  netCDF_Crawler crawl;
  return crawl.Find(attributes, currStep, lastStep);
}

template<typename U>
void netCDF_Attributes< U > :: Initialise(std::multimap< std::string, U > &attMap ){
  for ( auto iter : attMap )
    attributes.insert( std::pair< std::string,  netCDF_Attribute< U > >( iter.first,  netCDF_Attribute< U >(iter.second) ) ); 
}

enum netCDF_Element {groupElement, attributeElement, dimensionElement, variableElement, dataElement};

class netCDF_Crawler {
public:
  template<typename T>
  boost::optional<T * > Shallow_Search_List(const std::multimap< std::string, T > &currMap, std::string name);
  template<typename T>
  boost::optional< std::pair<netCDF_Element, void *> > Deep_Search_List(const std::multimap< std::string, T > &currMap,
                                       std::vector< std::string >::iterator currStep, 
                                       std::vector< std::string >::iterator lastStep);
  template<typename T>
  boost::optional< std::pair< netCDF_Element, void * > > Find(const std::multimap< std::string, T > &currMap,
                                std::vector< std::string >::iterator currStep, 
                                std::vector< std::string >::iterator lastStep);
};

  template<typename T>
  boost::optional<T * > netCDF_Crawler::Shallow_Search_List(const std::multimap< std::string, T > &currMap, std::string name){
    for (auto iter : currMap)
      if (iter.first == name)
    return &iter.second;
    return boost::none;
  }

template<typename T>
  boost::optional< std::pair< netCDF_Element, void * > > netCDF_Crawler::Deep_Search_List(const std::multimap< std::string, T > &currMap,
                                               std::vector< std::string >::iterator currStep, 
                                               std::vector< std::string >::iterator lastStep){
    for (auto iter : currMap)
      if ( boost::optional< std::pair< netCDF_Element, void * > > res = iter.second.Find(currStep, lastStep) )
    return res;
    return boost::none;
  }

template<typename T>
  boost::optional< std::pair< netCDF_Element, void * > > netCDF_Crawler::Find(const std::multimap< std::string, T > &currMap,
                                        std::vector< std::string >::iterator currStep, 
                                        std::vector< std::string >::iterator lastStep){

    if (boost::optional< T* > currPtr = Shallow_Search_List< T >(currMap, *currStep))
      // Found in map.
      // This was the last element to find.
      if (currStep == lastStep)
    return std::pair< netCDF_Element, void * > ((*currPtr)->element, (void *) *currPtr);
      else
    // Try and find the next element
    return (*currPtr)->Find(currStep+1, lastStep);
    // Not found in curr map.  Dig deeper. Look in subgroups.
    else 
      return Deep_Search_List<T>(currMap, currStep, lastStep);
    return boost::none;
  }

第一条错误消息是:

Class_netCDF_Attributes.hpp: In instantiation of
‘boost::optional<std::pair<netCDF_Element, void*> > netCDF_Attributes<U>::Find
  (std::vector<std::__cxx11::basic_string<char> >::const_iterator, 
   std::vector<std::__cxx11::basic_string<char> >::const_iterator)
[with U = netCDF::NcVarAtt;
 std::vector<std::__cxx11::basic_string<char> >::const_iterator = 
   __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >]’:
Class_netCDF_Variable.hpp:55:98:   required from here
Class_netCDF_Attributes.hpp:34:51: error: no matching function for call to 
‘netCDF_Crawler::Find(std::multimap<std::__cxx11::basic_string<char>, netCDF_Attribute<netCDF::NcVarAtt>, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, netCDF_Attribute<netCDF::NcVarAtt> > > >&,
                      std::vector<std::__cxx11::basic_string<char> >::const_iterator&,
                      std::vector<std::__cxx11::basic_string<char> >::const_iterator&)’
   return crawl.Find(attributes, currStep, lastStep);

1 个答案:

答案 0 :(得分:0)

简而言之:您提供了错误的参数类型。

在您的代码中很难发现,因为它相当混乱。因此,首先要解决问题的方法是首先将问题减少到MCVE。 这是一个很小的版本,可以重现你的错误:

struct netCDF_Crawler {
  template<typename T>
  T find(std::multimap<std::string,T> const&, std::vector<std::string>::iterator);
};

template<typename U>
struct netCDF_Attribute { U i=U{}; };

template<typename U>
struct netCDF_Attributes
{
  std::multimap<std::string,netCDF_Attribute<U>> attributes;
  netCDF_Attribute<U> find(std::vector<std::string>::const_iterator step)
  {
    netCDF_Crawler crawl;
    return crawl.find(attributes,step);
  }
};

template struct netCDF_Attributes<int>;

这个代码看错误是显而易见的,但让我们看看clang说的是什么(顺便说一下,第二个非常有用的注释只是在减少了find()的参数数量之后产生的3至2):

test.cc:21:18: error: no matching member function for call to 'find'
    return crawl.find(a,step);
           ~~~~~~^~~~
test.cc:25:17: note: in instantiation of member function 'netCDF_Attributes<int>::find'
  requested here
template struct netCDF_Attributes<int>;
                ^
test.cc:7:5: note: candidate function [with T = netCDF_Attribute<int>] not viable:
 no known conversion from '__wrap_iter<const_pointer>' to '__wrap_iter<pointer>'
 for 2nd argument
  T find(std::multimap<std::string,T> const&, std::vector<std::string>::iterator);
    ^
1 error generated.

经过检查,我们发现netCDF_Crawler::finditerator作为第二个参数,而netCDF_Attributes::find()则提供const_iterator。显然,这不会起作用。我留给你修理。