在一个向量中保存具有不同模板参数的类实例,但保留其属性

时间:2016-01-27 18:26:07

标签: c++ templates sfinae

我想有一个程序来解析和管理命令行参数。正如您在this - 函数中所看到的,通过使用main之类的简单命令,您可以指定选项值应具有的类型(在本例中为Option<int>("number", { "-n", "--number" })),每个选项的唯一标识符(如int),以及可以引入此选项的多个字符串。此外,许多选项应包含在名为"number"的类中,这样可以简化对其选项的访问。

但在我的实际代码中,我现在遇到了几个问题:

  1. 我想在一个OptionSet内存储一个具有不同模板参数的类的多个实例。例如,在我的代码中,std::vector应存储在Option<int>Option<std::string>等相同的向量中。 也许甚至可以将模板参数分别存储在另一个向量中?
  2. 使用Option<double>usingstd::enable_if_t我创建了一个名为std::is_same的类型。如果模板参数OptionHasValue为false且InvertT,则void的类型无效,否则它具有模板参数OptionHasValue指定的类型。
    U使用OptionValue和一些SFINAE魔法来决定它是否应该具有支持值存储所需的方法。也就是说,OptionHasValue的第一个版本具有OptionValue作为其第二个模板参数,因此如果OptionHasValue<T>T,它将变为无效(并由编译器删除)。另一个版本的void具有相反的行为,因为其第二个模板参数为OptionValueOptionHasValue<T, true>反转了true的行为。
    OptionHasValue本身继承自Option,因此如果您创建类似OptionValue的选项,则它不支持值(即,它缺少Option<void>之类的函数,应该setValuesetValueFromString。另一方面,如果您创建类似getValue的选项,则生成的类实例具有所有这些功能 现在的问题是,(例如)Option<int>访问OptionSet::process()Option::hasValue,但后者仅在Option::setValueFromString为真时声明(以及相应的模板参数该选项不是Option::hasValue)。但由于void未包含在某种模板中,编译器也会抱怨。
  3. 在我的Option::setValueFromString - 函数中,我使用函数main。此函数应返回选项的值(在调用optionSet.getOptionValue(std::string)后设置之后)。现在最困难的是返回类型取决于process()的返回值,该函数循环遍历所有可用选项并返回带有所需标识符的选项。
    例如,如果findOptionByIdentifieridentifier(如本问题开头的"number"示例所示),则Option的返回类型为{{1}因为唯一具有标识符findOptionByIdentifier的选项是Option<int>作为其第一个模板参数的选项,最终会导致"number"具有返回类型int
    您可以在getOptionValue - 函数的最后几行中查看注释中的预期行为。
  4. 那么,我需要在以下代码中修改以修复所有这些内容(并使其编译)?我使用的是g ++ 5.2.0(mingw-w64),所以我可以使用C ++ 11和C ++ 14的任何功能。

    int

1 个答案:

答案 0 :(得分:0)

我不确定我是否完全理解这个问题,但我会尽力回答。

  

我想存储一个具有不同类的多个实例   模板参数

没有这样的事情。具有不同模板参数的模板是不同的类。但是,您似乎通过boost::any成功解决了这个问题。您还可以使用其他类型删除技术 - 例如,为您的所有选项设置非模板父级,或切换到非类型删除boost::variant,因为您似乎只有有限数量的可能选项类型。

  

通过使用using,std :: enable_if_t和std :: is_same我创建了一个类型   叫做OptionHasValue ......

首先,我不会在这个例子中使用SFINAE。简单的部分专业化就足够了。至于opt.setValueFromString(argvVec[i]);,只需在void选项类中创建一个NOOP函数。

关于最后一个问题,只需使用模板化函数接收对返回类型的引用,而不是返回它。