模板函数返回不同的类型

时间:2013-04-28 11:17:09

标签: c++ function templates generics

是否可以使用在运行时确定的类型返回不同类型的方法?

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

为了避免编写三个(现在有三个密码)单独的方法来返回不同类型的密钥,并且一次只使用一个密码我正在尝试执行以下操作:

parser.h中的

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

/**
 * The key to be used for encoding or decoding.
 * 
 * @return      The key to be used.
 */
template <typename T>
T cmdline_parser::get_key(void) const
{
    if (vm.count("xor") > 0)// if xor cipher in use
        return vm["xor"].as<long>();// returns a key of type long
    else if (vm.count("caesar") > 0)// if caesar cipher in use
        return vm["caesar"].as<int>();// returns a key of type int
    else// vignere cipher in use
        return vm["vignere"].as<std::string>();// returns a key of type std::string

}

我是如何尝试使用它的:

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;
  ^

1 个答案:

答案 0 :(得分:1)

您可以使用3种方法,所有这些方法都在评论中提到。以下是更多细节和权衡,可供选择:

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

  2. <强> Boost.Variant 即可。 @AnatolyS在评论中提到了这一点。此方法在联合中包含有限数量的不相关类型,并允许您在没有动态分配开销的情况下仅使用其中一种类型。有关如何使用它的信息,请参阅Boost文档。主要缺点是它不是非常可扩展的,动态选择你想要的密钥类型需要bit of trickery

  3. <强> Boost.Any 即可。这概括了两个解决方案,以便在持有者对象内包含任意数量的不相关类型。主要的优点是你有价值语义,没有手动内存管理(虽然这是在幕后完成的)。唯一的实际缺点是它需要Boost,这在某些限制性公司环境中是不可能的。