强制使用特定类型的可变模板
Enforce variadic template of certain type
本文关键字:类型 更新时间:2023-10-16
我想强制可变模板的类型与先前设置的模板类型相同。在下面的例子中,我希望T和U是相同的类型。
ideone.com的代码
#include <iostream>
#include <string>
template<class T>
struct Foo {
Foo(T val) {
std::cout << "Called single argument ctor" << std::endl;
// [...]
}
// How to enforce U to be the same type as T?
template<class... U>
Foo(T first, U... vals) {
std::cout << "Called multiple argument ctor" << std::endl;
// [...]
}
};
int main() {
// Should work as expected.
Foo<int> single(1);
// Should work as expected.
Foo<int> multiple(1, 2, 3, 4, 5);
// Should't work (but works right now). The strings are not integers.
Foo<int> mixedtype(1, "a", "b", "c");
// Also shouldn't work. (doesn't work right now, so that is good)
Foo<int> alsomixedtype(1, 1, "b", "c");
}
我们可以使用SFINAE来确保所有U
类型都与T
相同。需要注意的重要一点是,U
不只是您所暗示的一种类型,而是可能不同类型的列表。
template<class... U, std::enable_if_t<all_same<T, U...>::value>* = nullptr>
Foo(T first, U... vals) {
std::cout << "Called multiple argument ctor" << std::endl;
// [...]
}
std::enable_if_t
来自c++ 14。如果你没有这个选择,就使用std::enable_if
。
typename std::enable_if<all_same<T, U...>::value>::type* = nullptr>
all_same
可以通过多种不同的方式实现。下面是我喜欢使用布尔包的方法:
namespace detail
{
template<bool...> struct bool_pack;
template<bool... bs>
//if any are false, they'll be shifted in the second version, so types won't match
using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;
}
template <typename... Ts>
using all_true = detail::all_true<Ts::value...>;
template <typename T, typename... Ts>
using all_same = all_true<std::is_same<T,Ts>...>;
std::conjunction
(逻辑与)在c++ 17中引入,因此不再需要手动实现all_same
。然后构造函数变得简单:
template<typename... U,
typename = std::enable_if_t<
std::conjunction_v<
std::is_same<T, U>...
>
>
>
Foo(T first, U... vals)
{
std::cout << "Called multiple argument ctor" << std::endl;
// [...]
}
c++的20个概念使它像
一样简单 template<std::same_as<T>... U>
Foo(T first, U... vals) {
std::cout << "Called multiple argument ctor" << std::endl;
// [...]
}
https://gcc.godbolt.org/z/neEsvo 如果要求所有参数为相同类型且参数个数可变,
可变模板对于这些要求来说太重了,只需使用 c++ 11 std::initializer_list。
如果你能在调用时用{}替换(),它们就能完成任务。
template<class T> struct Foo {
Foo(T val) {
std::cout << "Called single argument ctor" << std::endl;
}
// Enforce all parameters to be the same type :
Foo( std::initializer_list<T> values ) {
std::cout << "Called multiple argument ctor" << std::endl;
for (T value : values)
cout << value << endl;
}
};
int main() {
// Work as expected.
Foo<int> single(1);
// Work as expected.
Foo<int> multiple{ 1, 2, 3, 4, 5 };
// Doesn't work - as required :
//Foo<int> mixedtype{ 1, "a", "b", "c" };
}
在不实现all_same
的情况下,您还可以更改构造函数代码,如下所示:
template<class F, typename = typename enable_if<is_same<F, T>::value>::type, class... U>
Foo(F first, U... vals): Foo(vals...) {
std::cout << "Called multiple argument ctor" << std::endl;
// [...]
}
is_same
是STL中的函数<type_traits>
相关文章:
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 构造函数正在调用一个使用当前类类型的函数
- 我应该使用什么来代替void作为变体中的替代类型之一
- 类中的字符串不命名类型