【问题标题】:partial ordering variadic template function clang部分排序的变型模板函数克朗
【发布时间】:2015-06-17 05:18:33
【问题描述】:

我目前正在使用 Boost.ProgramOptions 进行项目,我必须创建以下结构来为选项添加一些约束:

template <const char *str1, const char*... str2> 
struct restrictedValues
{
...
};

为了验证新选项,您必须重载 boost::program_options::validate 函数:

template<class T, class charT>                                                                            
void validate(boost::any& v, const std::vector< std::basic_string<charT> >& xs, T*, long);

这个验证函数的调用如下:

validate(value_store, new_tokens, (T*)0, 0);

正如 boost 所言:“目标类型是通过一个参数指定的,该参数具有指向所需类型的指针类型。这是没有部分模板排序的编译器的解决方法,就像最后一个 'long/int' 参数一样。”

因此,我以以下方式编写了我的验证版本:

template<class charT, const char *... str>
void validate(boost::any &v,
        const std::vector<std::basic_string<charT> >& values,
        restrictedValues<str...>* /*target_type*/,
        int /*unused*/) { ... }

看起来我的 clang 版本(Ubuntu clang 版本 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final)(基于 LLVM 3.5.0))只是跳过了我的版本并在默认版本中正常失败。虽然我的 gcc ((Ubuntu 4.8.2-19ubuntu1) 4.8.2) 愉快地编译。

编辑查看显示不同行为的实时示例,感谢@dyp:

Live On Coliru

#include <boost/any.hpp>
#include <vector>
#include <string>
#include <iostream>

template <const char *str1, const char*... str2> struct restrictedValues                                                                                
{
/*...*/
};

template<class T, class charT>                                                                            
void validate(boost::any&, const std::vector< std::basic_string<charT> >&, T*, long)
{
    std::cout << "default version\n";
}

extern char const client[] = "hello";
extern char const server[] = "world";

template<class charT, const char *... str>
void validate(boost::any &,
        const std::vector<std::basic_string<charT> >&,
        restrictedValues<str...>* /*target_type*/,
        int /*unused*/) {
    std::cout << "custom version\n";
}

int main()
{
    boost::any a;
    std::vector<std::string> xs;
    restrictedValues<client, server>* p = 0;
    validate(a, xs, p, 0);
}

此外,对结构/函数使用非可变模板(固定数量的 const char*)的相同过程确实像一个魅力。

我不太确定哪个查找过程会导致这种模棱两可的错误。 如果我的函数没有使用模板,它会根据重载规则进行选择,但事实并非如此。通过阅读模板函数的部分排序规则,两个函数对模板参数具有相同的特化,但我的期望是 int/long 技巧应该起作用。关于如何解决这个模板之谜的任何想法?

【问题讨论】:

  • 我的错误复制粘贴。更正了它。问题还是一样。
  • 我以前见过这个。与operator&lt;&lt;s 或Boost Serialization 的serialize/load/save 自定义点类似。老实说,我认为这是一个非常有趣的问题,但除非包含 SSCCE,否则它不会得到应有的关注。我认为它可能在
  • @sehe Like that? (我自己也很好奇:)
  • Clang 3.6.0 选择自定义版本,不仅针对问题中的确切代码,而且如果您将默认版本的签名中的long 更改为int,以强制使用偏序规则。
  • @dyp 我用-Wall -Wextra -std=c++14 -pedantic编译它,所以我不认为它是一个扩展。 GCC 4.9.2、MSVC12 和 14 都编译代码没有警告(这个super-simplified version 来自你的)。我想说应该推导出该参数包的参数,然后替换显然应该起作用。我投票赞成修复错误。

标签: c++ templates c++11 boost-program-options partial-ordering


【解决方案1】:

这里通常的方法是使用强类型定义使 ADL 工作。

我已在较早的答案中记录了这一点¹:


¹那里的第一个 cmets 已过时,请参阅我之前的旧答案。

【讨论】:

  • 我不确定这是否有助于 OP。 OP 正在尝试推断一包字符串,但 clang 无法做到。
  • @dyp 我不会因为 std::vector 和 std::basic_string 关联 std 命名空间而感到惊讶。我只是把这个放在这里。稍后我可能有时间实际测试一下
  • 我认为它失败的原因是因为类模板有一个非包模板参数加上一个包,而OP只是推导出一个包。 works with matching parameters in deduction; fails without additional template param in clang
  • 添加非打包参数确实解决了我的问题。但目前尚不清楚为什么不推导出完整的可变参数模板。
猜你喜欢
  • 2015-02-18
  • 2016-01-30
  • 2017-04-24
  • 2021-03-19
  • 2020-05-31
  • 1970-01-01
  • 1970-01-01
  • 2011-09-28
  • 2010-11-13
相关资源
最近更新 更多