【问题标题】:Template function to return different types返回不同类型的模板函数
【发布时间】:2013-04-28 11:17:08
【问题描述】:

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

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

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

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&lt;VignereCipher, std::string, Group, Pack&gt; 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;
  ^

【问题讨论】:

  • 函数没有参数,编译器无法从任何地方推断出类型。
  • 您听说过变体类型吗?该变体将解决您的问题。
  • 听起来像是多态类层次结构和工厂的经典案例。
  • vm 是什么set
  • @AnatolyS 我从未听说过变体类型? @jrok vm 是 boost::program_options::variables_map

标签: c++ function templates generics


【解决方案1】:

您可以使用 3 种方法,所有这些方法都在 cmets 中提及。以下是在它们之间进行选择的更多细节和权衡:

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

  2. Boost.Variant。 @AnatolyS 在 cmets 中提到了这一点。这种方法将有限数量的不相关类型包装在一个联合中,并允许您一次只使用其中一种类型,而无需动态分配开销。请参阅 Boost 文档了解如何使用它。主要缺点是扩展性不是很好,需要相当大的bit of trickery才能动态选择你想要的key类型。

  3. Boost.Any。这将两种解决方案概括为在持有者对象中包含任意数量的不相关类型。主要优点是您具有值语义,并且没有手动内存管理(尽管这是在幕后完成的)。唯一实际的缺点是它需要 Boost,这在一些限制性的公司环境中是不可能的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 2011-03-04
    相关资源
    最近更新 更多