2015-07-01 101 views
1

编辑:我可以简化以下模板吗?

感谢您的优秀答案。我显然没有给出我的问题足够的细节。我试图纠正这一点,

我更新一些旧代码,并有几个重载函数具有以下模式:

void foo (Int bla, const char* bla1, const char* bla2, ...); 
void foo (Int bla, SomeCustomContainer); 

现在,我们正在逐步淘汰的自定义容器,并使用std容器代替。自定义容器的签名是这样的,我可以在continainer上进行模板化,重新使用代码,并同时支持旧代码和新代码,直到遗留代码被淘汰。

我的第一个尝试是:

template <typename ContainerT> void foo(int bla, ContainerT); 

但是编译器吐出了一个错误,原因是其在为const char *签名的模板函数相匹配。

基于StackOverflow上一个答案,我想下面的模板签名:

template <typename ValT, template <typename, typename = std::allocator<ValT> > 
      class ContainerT> 
void foo(Int bla, const ContainerT<ValT>& rasInParams) 

这解决我的问题 - 编译器找到正确的过载,一切工作正常,我的目的。我唯一的抱怨是,对于一个对模板不太熟悉的同事来说,这是一个很大的分析,我想知道是否有一种方法可以简化它 - 我正在考虑使用类型别名,但也许有人知道更好的方法来解决我的基础重载解决问题?

+0

什么叫 “更容易阅读” 期待? – davidhigh

+0

我认为这两个答案仍然有效的更新的问题。你所要做的就是向'SomeCustomContainer'类中添加'value_type'类型定义(如果它们不存在的话)(或者你也可以在@ sehe的答案中使用'begin()'开始使用这个技巧) –

+0

@Anton Savin:对不起,我没有得到你想说的话 - 如果是我当前的解决方案和通过各种定制容器并修改它们(当目标只是将其删除时)之间的选择,我更喜欢当前的解决方案。我的问题不是我需要知道值类型,而是编译器发现错误的函数重载(不是模板实现,而是接受char *)。 – Spacemoose

回答

1

你可以简单的写(前提是你使用的是标准的容器中,作为参数):

template <typename ContainerT> 
void foo(const ContainerT& rasInParams) { 
    using ValT = typename ContainerT::value_type; 
    // ... 
} 

如果你想foo不参与重载决议如果参数不是一个容器,可以用SFINAE。这仍然看起来比你原来的代码更简单:

template <typename ContainerT, typename = ContainerT::value_type> 
void foo(const ContainerT& rasInParams) 
+0

我认为你最近的编辑是按照我想要的方向进行的,但是按照书面方式,它不能在我的自定义容器上解析。我不清楚typename = ContainerT :: value_type是干什么的。 – Spacemoose

2

的样品不一般工作(想象,不接受一个allocator,或需要两个以上的类型参数,或上帝保佑的容器,非类型参数)。

我通常的做法是只为了

template <typename Container> 
void foo(const ContainerT& rasInParams) 

如果你需要知道你可以做任何事情一样

typename Container::value_type 

std::remove_reference<decltype(*rasInParams.begin())>::type 

如果你真的是值类型需要嵌入一个可配置的容器f ROM模板的模板参数,你可以使用一个可变参数签名嵌套一个:

template<typename ValT, template<T...> class Container> 
void foo() { 
    Container<ValT, std::allocator<ValT> > x; 
} 

另一种选择是去同一个容器“选择”元功能。这是例如在Boost图库使用:

+0

@davidhigh谢谢,修正 – sehe