2013-04-28 41 views
1

是否有可能让方法返回不同类型的值,并且在运行时确定类型?返回不同类型的模板函数

我正在写一些东西,将使用不同的密码进行编码和解码。每个密码都有一个不同类型的密钥,并且在某个阶段,我需要允许密码获取此密钥。

为了避免写的三(有三个密码现在)不同的方法以返回不同类型的钥匙,而只有一个密码将在同一时间,我尝试做以下使用:

parser.h

template <typename T> 
    T get_key(void) const; 
parser.cpp

​​

如何我想使用它:

Crypt<VignereCipher, std::string, Group, Pack> c(parser.get_key());

clang++编译给出:

main.cpp:42:61: error: no matching member function for call to 'get_key' 
    Crypt<VignereCipher, std::string, Group, Pack> c(parser.get_key()); 
               ~~~~~~~^~~~~~~ 

./cmdline_parser.h:40:7: note: candidate template ignored: couldn't infer template   argument 'T' 
T get_key(void) const; 
^
+0

函数没有参数,编译器无法从任何地方推导出类型。 – jrok 2013-04-28 11:19:23

+0

你听说过变体类型吗?该变种将解决您的问题。 – AnatolyS 2013-04-28 11:20:15

+2

听起来像一个多态的类层次结构和工厂的经典案例。 – 2013-04-28 11:20:48

回答

1

有,你可以使用,所有这些都在评论中提到的3种方法。这里有一些更多的细节,并权衡它们之间选择:

  1. 工厂方法。正如@KerrekSB在评论中提到的那样,你必须定义一个抽象基类,并从中为每个类型定义子类。工厂函数的返回类型是一个指针(最好是处理资源管理的智能指针)到AbstractKey。然而,工厂的实现是基于您正在解析的运行时值的if-else梯形图,switch语句或花式表查找。这是因为covariant return types。有关工作示例,请参阅这个site关于设计模式。主要的缺点是需要编写大量的样板文件(例如,将新类型注册到工厂等),内建类型被排除,并且返回的对象没有值语义。

  2. Boost.Variant。 @AnatolyS在评论中提到了这一点。这种方法在联合体中包含有限数量的不相关类型,并且允许您在此时仅使用其中一种类型,而无需动态分配开销。请参阅Boost文档以了解如何使用它。主要的缺点是它不是很可扩展,并且需要大量的bit of trickery才能动态选择所需的密钥类型。

  3. Boost.Any。这概括了这两种解决方案都有一个包含在一个持有者对象内的任意数量的不相关的类型。主要优点是你有价值语义,并且没有手动内存管理(尽管这是在场景后面完成的)。唯一的缺点是它需要Boost,这在一些限制性的公司设置中是不可能的。