c++ - std::is_convertible 的可变参数版本?

标签 c++ variadic-templates

是否可以编写 std::is_convertible 的可变版本?例如are_convertible<T1, T2, T3, T4>会返回 is_convertible<T1, T3> && is_convertible<T2, T4> .我已经考虑了几个小时,但想不出任何合理的想法。

澄清一下,我想像这样使用它:

template <class ...Args1>
struct thing
{
  template <class ...Args2>
  enable_if_t<are_convertible<Args2..., Args1...>::value>
  foo(Args2 &&...args){}
}

最佳答案

您不需要连接 Args2...Args1... ,你不应该这样做,因为这样做会让人无法分辨 Args2... 在哪里。结束和Args1...开始。以允许单独提取它们的方式传递多个可变参数的方法是将它们包装在另一个模板中:给定一个可变参数模板 my_list , 你可以构建你的 my_convertible被称为

my_convertible<my_list<Args2...>, my_list<Args1...>>

标准库已经有一个在这里运行良好的可变参数模板:tuple .不仅如此,tuple<Args2...>可转换为 tuple<Args1...>当且仅当 Args2...可转换为 Args1... , 所以你可以这样写:

std::is_convertible<std::tuple<Args2...>, std::tuple<Args1...>>

注意:在评论中,@zatm8 报告说这并不总是有效:std::is_convertible<std::tuple<const char *&&>, std::tuple<std::string &&>>::value报告为 false ,但是 std::is_convertible<const char *&&, std::string &&>::value报告为 true .

我认为这是一个错误,它们都应该报告为 true .该问题可在 http://gcc.godbolt.org/ 上重现随着 3.9.1 的 clang 。它不能用 gcc 6.3 重现,并且在使用 -stdlib=libc++ 时也不能用 clang 3.9.1 重现。 .看起来 libstdc++ 正在使用 clang 不能完全正确处理的语言功能,并将其简化为一个不依赖于标准库头文件的简短示例:

struct S {
  S(const char *) { }
};
int main() {
  const char *s = "";
  static_cast<S &&>(s);
}

这被 gcc 接受,但被 clang 拒绝。它在 2014 年被报道为 https://llvm.org/bugs/show_bug.cgi?id=19917 .

这似乎已在 2016 年底修复,但修复尚未进入发布版本:http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20161031/175955.html

如果你受此影响,不妨避开std::tuple并改用@Yakk 的答案。

关于c++ - std::is_convertible 的可变参数版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34615570/

相关文章:

c++ - 如何在VS Code中运行测试和调试Google Test项目?

c++ - 通过 TCP 实现 TLV 协议(protocol)

c++ - 从 unordered_map 获取键和值列表

c++ - 实例化模板参数的参数包

c++ - 为什么打印B的时候多了一个空行?

c++ - rand() 函数生成错误范围内的数字

c++ - 使用 std::tuple 传递 c++ 模板包是否有任何原因

c++ - 将 nullptr 传递给可变模板指针

c++ - 模板参数包中的 6 个点是什么?

c++ - 捕获可变参数模板类型?