是否可以编写 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/