std::is_convertable的可变版本
Variadic version of std::is_convertible?
是否可以编写可变版本的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
。不仅如此,而且当且仅当Args2...
可转换为Args1...
时,tuple<Args2...>
可转换为tuple<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的叮当声。当使用-stdlib=libc++
时,它不能用gcc 6.3再现,也不能用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的答案。
是。
首先,如何做。然后,为什么你不应该做。
如何做到:
写regroup,它取一个kN元素的列表,并将其分组为N组k,交错排列。组可以是template<class...>struct types{};
。
然后写apply,它获取组的template<class...>class Z
和class...
(也称为types<...>
),并将Z
应用于每个束的内容,返回结果的types<...>
。
然后使用template<class A, class B> struct and_types:std::integral_constant<bool, A{}&&B{}>{};
折叠types<...>
的内容。
我会觉得这几乎毫无意义,所以我不会实现它。有了一个像样的元编程库应该很容易,上面的大多数操作都是标准的。
为什么你不应该
但实际上,举个例子,就这么做吧:
template<class...Ts>
struct and_types:std::true_type{};
template<class T0, class...Ts>
struct and_types<T0,Ts...>:std::integral_constant<bool, T0{} && and_types<Ts...>{}>{};
然后:
std::enable_if_t<and_types<std::is_convertible<Args2, Args1>...>{}>
做这项工作。所有的洗牌都只是噪音。
有了C++1z对折叠...
的支持,我们也去掉了and_types
,只使用了&&
和...
。
您可以使用std::conjuction将所有结果类型折叠为一个:
template <class... Args>
struct is_convertible_multi {
constexpr static bool value = false;
};
template <class... Args1, class... Args2>
struct is_convertible_multi<::std::tuple<Args1...>, ::std::tuple<Args2...>> {
constexpr static bool value = ::std::conjunction_v<::std::is_convertible<Args1,Args2>...>;
};
记得检查
sizeof... (Args1) == sizeof... (Args2)
使用if constexpr或enable_if
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 导入库可以跨dll版本工作吗
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 在clang++预处理器中确定gcc工具链版本
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 不同的Visual Studio版本中缺少.dll
- 用符号版本替换对函数的所有调用
- luaL_dofile在已知良好的字节码上失败,可以使用未编译的版本
- 正在解码MSVC 32位版本的程序集(作业).没有手术做什么
- 我需要分发哪些版本的可再分发文件
- CV_OCL_RUN宏如何在OpenCV(版本3.4.5)的goodFeaturesToTrack实现中工作?
- 在运行时读取 libstdc++ 版本
- 如何声明一个可以在整个程序中使用的全局 2d 3d 4d .. 数组(堆版本)变量?
- FindPackageHandleStandardArgs.cmake:137 的 CMake 错误(消息):找不到 Boost (缺少:正则表达式)(找到合适的版本"1.72.0",
- Vulkan SDK 版本 1.1.85.0 在 Kubuntu 18.10 上链接
- 如何正确实现与基类不同的版本?
- 从预处理器获取 Windows 版本(C++ Win32)
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 如何在C++中将 Python 字符串转换为其转义版本?
- Qt版本应该在其他计算机上运行吗?