我想要这样的类(class):
template<typename T>
struct Foo {
T* data_;
template<typename... Ts, std::enable_if<std::is_same<T,Ts>...>...>
explicit Foo(Ts...ts) : data_{ ts... } {}
};
但是;语法有问题,我不确定在初始化时是否可以像这样直接将参数设置为指针。
我希望它做的只是这样:
Foo<int> f1{ 1, 3, 5, 7 }; // Or
// Foo<int> f1( 1, 3, 5 7 );
// f1.data_[0] = 1
// f1.data_[1] = 3
// f1.data_[2] = 5
// f1.data_[3] = 7
// f1.data_[4] = ... not our memory either garbage or undefined...
Foo<float> f2{ 3.5f, 7.2f, 9.8f }; // Or
// Foo<float> f2( 3.5f, 7.2f, 9.8f );
// f2.data_[0] = 3.5
// f2.data_[1] = 7.2
// f2.data_[2] = 9.8
// f2.data_[3] = ... not our memory
我还想让构造函数检查以确保传递给构造函数的每个参数都是 <T>
类型的;简单地把每个 Ts
它必须是 T
.
我可能想得太多了,但对于我来说,我无法得到这个或类似的东西来编译。不知道是不是在enable_if
里面, is_same
或者通过类的初始化列表并尝试将内容存储到指针中。我不知道我是否应该使用 T
的数组相反,在将参数传递给构造函数之前,数组的大小是未知的。我也尝试在不使用基本容器(例如 std::vector
)的情况下执行此操作;它比实用的源代码更适合 self 教育。我只想看看如何使用原始指针完成此操作。
编辑
我把我的类(class)改成了这样:
template<typename T>
struct Foo {
T* data_;
template<typename... Ts, std::enable_if_t<std::is_same<T, Ts...>::value>* = nullptr>
explicit Foo( const Ts&&... ts ) : data_{ std::move(ts)... } {}
};
尝试使用它时:
int a = 1, b = 3, c = 5, d = 7;
Foo<int> f1( a, b, c, d );
Foo<int> f2{ a, b, c, d };
这次迭代我更接近了一点;但它们都给出了不同的编译器错误。
- 第一个是:
C2661
: “没有重载函数需要 4 个参数” - 第二个:
C2440
: “正在初始化,无法从初始化列表转换为容器,没有构造函数可以采用源类型,或者构造函数重载解析不明确。”
最佳答案
为什么不简单地使用 std::initialize_list:
?
#include <iostream>
#include <type_traits>
#include <vector>
template <class T>
struct Foo
{
std::vector<T> data_;
explicit Foo(std::initializer_list<T> data) : data_(data)
{
std::cout << "1";
};
template <typename... Ts,
typename ENABLE=std::enable_if_t<(std::is_same_v<T,Ts> && ...)> >
explicit Foo(Ts... ts) : Foo(std::initializer_list<T>{ts...})
{
std::cout << "2";
}
};
int main()
{
Foo<int> f1{1, 3, 5, 7}; // prints 1
Foo<int> f2(1, 3, 5, 7); // prints 1 then 2
return 0;
}
如果某些 T
与 T
不同,您将遇到编译时错误。
与
gcc -std=c++17 prog.cpp
你得到:
Foo<int> f1{1, 3, 5., 7};
error: narrowing conversion of ‘5.0e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing] Foo f1{1, 3, 5., 7}; ^
和
Foo<int> f2(1, 3, 5., 7);
你得到了
error: no matching function for call to ‘Foo::Foo(int, int, double, int)’ Foo f2(1, 3, 5., 7); ^ note: candidate: ‘template Foo::Foo(Ts ...)’ explicit Foo(Ts... ts) : Foo(std::initializer_list{ts...})
...
更新:如果您真的想使用类似原始指针的东西,这里有一个完整的工作示例:
#include <iostream>
#include <memory>
#include <type_traits>
#include <vector>
template <class T>
struct Foo
{
size_t n_;
std::unique_ptr<T[]> data_;
explicit Foo(std::initializer_list<T> data) : n_(data.size()), data_(new T[n_])
{
std::copy(data.begin(), data.end(), data_.get());
std::cout << "1";
};
template <typename... Ts, typename ENABLE = std::enable_if_t<(std::is_same_v<T, Ts> && ...)> >
explicit Foo(Ts... ts) : Foo(std::initializer_list<T>{ts...})
{
std::cout << "2";
}
friend std::ostream& operator<<(std::ostream& out, const Foo<T>& toPrint)
{
for (size_t i = 0; i < toPrint.n_; i++)
std::cout << "\n" << toPrint.data_[i];
return out;
}
};
int main()
{
Foo<int> f1{1, 3, 5, 7}; // prints 1
Foo<int> f2(1, 3, 5, 7); // prints 1,2
std::cout << f1;
std::cout << f2;
return 0;
}
我让您用原始指针替换 unique_ptr 并完成所有额外工作:delete[] 等...
关于c++ - 确保模板参数类型与其可变构造函数的类型匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56311239/