确保模板参数类型与其可变参数构造函数类型匹配

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (46)

我想要一个这样的课程:

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_ifis_same还是通过类的初始化列表并尝试将内容存储到指针中。我不知道是否应该使用数组,T但是在将参数传递给构造函数之前,数组的大小是不可知的。我也试图在不使用基本容器的情况下这样做std::vector; 它比自己的实际源代码更适合自我教育。我只是想看看如何使用原始指针完成这项工作。

编辑

我把班级改成了这样的东西:

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 };

我对这个迭代更近了一点; 但他们都给出了不同的编译错误。

  • The first being: C2661: "No overloaded function takes 4 arguments"
  • And the second: C2440: "initializing, cannot convert from initializer list to Container, no constructor could take the source type, or constructor overload resolution was ambiguous."
提问于
用户回答回答于

在C ++ 17中最常用的方法是使用std::cunjunction_v。它懒惰地评估后续值并允许您避免折叠表达式。对于您在编辑的代码段中提到的两种情况,编译器生成的消息也是相同的。

此外,通过const-rvalue-ref传递数据毫无意义,因为无法从const对象移动数据。另外,你正在将一包参数移动到一个指针。我不知道该怎么办,所以就把它取下来。

另外,看看std::decay_t- 如果没有它它将无法工作,因为有时Ts推断不是int作为const int &int &。这导致了std::is_same_v错误。

下面的代码在godbolt编译得很好:

template<typename T>
struct Foo {
    T* data_;

    template<
        typename... Ts,
        std::enable_if_t<
            std::conjunction_v<
                std::is_same<T, std::decay_t<Ts>>...
            >
        > * = nullptr
    >
    explicit Foo( Ts&&... ts ) : data_{ } {}
 };
用户回答回答于

std::is_same仅比较两种类型,并且您不能使用包扩展来声明多个模板参数。这意味着您需要将所有std::is_same支票拉入另一张支票:

template <typename T, typename... Ts>
struct all_same : std::bool_constant<(std::is_same<T, Ts>::value && ...)> {};

template <typename T>
struct Foo
{
    std::vector<T> data_;

    template <typename... Ts, std::enable_if_t<all_same<T, std::decay_t<Ts>...>::value>* = nullptr>
    Foo(Ts&&... ts)
        : data_{std::forward<Ts>(ts)...}
    {
    }
};

现场演示

您还需要为data_阵列分配内存。在这里,我使用std::vector的照顾表示,分配给我,但你可以使用new[]delete[]自行管理它,如果你真的想。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励