Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在其他类中实现类似于数组的构造函数 在我所使用的所有现代C++编译器中,以下是合法的: std::array<float, 4> a = {1, 2, 3, 4}; std::数组a={1,2,3,4};_C++_Arrays_C++11_Variadic Templates - Fatal编程技术网

在其他类中实现类似于数组的构造函数 在我所使用的所有现代C++编译器中,以下是合法的: std::array<float, 4> a = {1, 2, 3, 4}; std::数组a={1,2,3,4};

在其他类中实现类似于数组的构造函数 在我所使用的所有现代C++编译器中,以下是合法的: std::array<float, 4> a = {1, 2, 3, 4}; std::数组a={1,2,3,4};,c++,arrays,c++11,variadic-templates,C++,Arrays,C++11,Variadic Templates,我试图创建自己的类,该类具有类似的构造语义,但我遇到了一个恼人的问题。考虑以下尝试: #include <array> #include <cstddef> template<std::size_t n> class float_vec { private: std::array<float, n> underlying_array; public: template<typename... Types> float_v

我试图创建自己的类,该类具有类似的构造语义,但我遇到了一个恼人的问题。考虑以下尝试:

#include <array>
#include <cstddef>

template<std::size_t n>
class float_vec
{
private:
  std::array<float, n> underlying_array;

public:
  template<typename... Types>
  float_vec(Types... args)
    : underlying_array{{args...}}
  {
  }
};

int main()
{
  float_vec<4> v = {1, 2, 3, 4}; // error here
}
#包括
#包括
模板
类浮点数
{
私人:
std::数组底层的_数组;
公众:
模板
浮动向量(类型…参数)
:基础_数组{{args…}
{
}
};
int main()
{
float_vec v={1,2,3,4};//此处出错
}
当像上面那样使用int文本时,编译器抱怨它不能隐式地将
int
转换为
float
。不过,我认为它在
std::array
示例中有效,因为给定的值是编译时常量,已知这些常量位于
float
域内。在这里,另一方面,变量模板使用
int
作为参数类型,并且转换发生在构造函数的初始值设定项列表中,其中的值在编译时是未知的

我不想在构造函数中执行显式强制转换,因为这样会允许所有数值,即使它们不能用
float
表示

我能想到的获得我想要的东西的唯一方法是以某种方式拥有一个数量可变的参数,但具有特定的类型(在本例中,我希望
float
)。我知道std::initializer\u list,但我也希望能够在编译时强制执行参数的数量


有什么想法吗?我想要的是C++11吗?对于C++14有什么新的建议可以解决这个问题吗?

您首先看到的是。它从最早的K&R C开始就存在了。如果您的类型是聚合,那么它已经支持聚合初始化了。另外,您的示例很可能会编译,但是初始化它的正确方法是
std::array x={{{1,2,3}(请注意双大括号)

在C++11中添加的是需要实现一些编译器魔法的构造

因此,您现在可以添加构造函数和赋值运算符,它们接受
std::initializer\u list
的值,这将为您的类型提供相同的语法

例如:

#include <initializer_list>

struct X {
  X(std::initializer_list<int>) {
    // do stuff
  }
};

int main()
{
  X x = {1, 2, 3};

  return 0;
}
提供一个
make.*
函数来推断参数的数量:

#include <array>

template<std::size_t N>
struct X {
  std::array<int, N> x;
};

template<typename... T>
auto make_X(T... args) -> X<sizeof...(T)>
// might want to find the common_type of the argument pack as well
{ return X<sizeof...(T)>{{{args...}}}; } 

int main()
{
  auto x = make_X(1, 2, 3);
  return 0;
}
#包括
模板
结构X{
std::数组x;
};
模板
自动生成X(T…args)->X
//可能还需要找到参数包的公共_类型
{返回X{{{{args…}};}
int main()
{
自动x=生成x(1,2,3);
返回0;
}

明确指定初始化的数据类型为浮点类型。你可以用“1.0f”代替“1”。如果是双精度,则输入“1.0d”。如果是长字符,则输入“1l”,对于未签名的长字符,则输入“1ul”,依此类推

我在这里测试过: 在这里:

你的代码很好。您刚刚初始化的类有点不正确

#include <array>
#include <cstddef>
#include <iostream>

template<std::size_t n>
class float_vec
{
private:
  std::array<float, n> underlying_array;

public:
  template<typename... Types>
  float_vec(Types... args)
    : underlying_array{{args...}}
  {
  }

  float get(int index) {return underlying_array[index];}
};

int main()
{
  float_vec<4> v = {1.5f, 2.0f, 3.0f, 4.5f}; //works fine now..

  for (int i = 0; i < 4; ++i)
    std::cout<<v.get(i)<<" ";
}
#包括
#包括
#包括
模板
类浮点数
{
私人:
std::数组底层的_数组;
公众:
模板
浮动向量(类型…参数)
:基础_数组{{args…}
{
}
float get(int-index){返回基础_数组[index];}
};
int main()
{
float_vec v={1.5f,2.0f,3.0f,4.5f};//现在可以正常工作了。。
对于(int i=0;i<4;++i)

std::cout如果使用多个大括号来初始化实例,则可以利用另一种类型的list init来接受编译时常量的这些转换。下面是一个使用原始数组的版本,因此构造时只需要parens+大括号:

#include <array>
#include <cstddef>

template<int... Is> struct seq {};
template<int N, int... Is> struct gen_seq : gen_seq<N-1, N-1, Is...> {};
template<int... Is> struct gen_seq<0, Is...> : seq<Is...> {};

template<std::size_t n>
class float_vec
{
private:
  std::array<float, n> underlying_array;

  template<int... Is>
  constexpr float_vec(float const(&arr)[n], seq<Is...>)
    : underlying_array{{arr[Is]...}}
  {}

public:
  constexpr float_vec(float const(&arr)[n])
    : float_vec(arr, gen_seq<n>{})
  {}
};

int main()
{
  float_vec<4> v0 ({1, 2, 3, 4});   // fine
  float_vec<4> v1 {{1, 2, 3, 4}};   // fine
  float_vec<4> v2 = {{1, 2, 3, 4}}; // fine
}
#包括
#包括
模板结构seq{};
模板结构gen_seq:gen_seq{};
模板结构gen_seq:seq{};
模板
类浮点数
{
私人:
std::数组底层的_数组;
模板
常量表达式浮点向量(浮点常量(&arr)[n],序号)
:基础_数组{{arr[Is]…}
{}
公众:
常量表达式浮点向量(浮点常量(&arr)[n])
:float_vec(arr,gen_seq{})
{}
};
int main()
{
float_vec v0({1,2,3,4});//很好
float_vec v1{{1,2,3,4};//很好
float_vec v2={{1,2,3,4};//很好
}

一个小技巧是使用构造函数继承。只需使您的类派生自另一个具有所需参数包的类即可

template <class T, std::size_t N, class Seq = repeat_types<N, T>>
struct _array_impl;

template <class T, std::size_t N, class... Seq>
struct _array_impl<T, N, type_sequence<Seq...>>
{
    _array_impl(Seq... elements) : _data{elements...} {}
    const T& operator[](std::size_t i) const { return _data[i]; }

    T _data[N];
};


template <class T, std::size_t N>
struct array : _array_impl<T, N>
{
    using _array_impl<T, N>::_array_impl;
};

int main() {
    array<float, 4> a {1, 2, 3, 4};
    for (int i = 0; i < 4; i++)
        std::cout << a[i] << std::endl;
    return 0;
}
模板
结构_数组_impl;
模板
结构_数组_impl
{
_数组\u impl(Seq…elements):\u数据{elements…}{}
常量T&运算符[](std::size_T i)常量{return_data[i];}
T_数据[N];
};
模板
结构数组:\u数组\u impl
{
使用_array_impl::_array_impl;
};
int main(){
数组a{1,2,3,4};
对于(int i=0;i<4;i++)

std::当然,在C++14中,
size()
std::initializer\u list
的函数将是
constepr
。我假设将您的类作为一个聚合是不可能的?OP只需要更新它们的编译器:正如您所看到的,它可以工作。它们的代码可以开箱即用。OP,get Mingw Builds 4.8.1如果在Windows上或在Linux上的g++4.8.1。
float\u vec(std::array p):基础_数组(std::move(p)){}
可以工作,但需要双/三个大括号以及数组参数的副本/移动。@CantChooseServerNames clang++3.5:[dcl.init.aggr]/2“如果初始值设定项子句是一个表达式,并且转换表达式需要进行窄化转换,则程序的格式不正确。”IIrg+++只将警告转换为警告。考虑使用完美的转发和通用引用在您的代码> MaxOxx()/Case>函数模板中。@ MAN324726肯定。我认为很明显这应该是一个原始类型而不是一个生产质量实现。“正确的初始化它的方法是<代码> STD::数组x= {{1,2,3};
”。该标准实际上只提到了单括号版本。从N3337 23.3.2.1.2开始:“数组是一个聚合,可以用语法
array a={initializer list};
初始化器列表是逗号se
template <class T, std::size_t N, class Seq = repeat_types<N, T>>
struct _array_impl;

template <class T, std::size_t N, class... Seq>
struct _array_impl<T, N, type_sequence<Seq...>>
{
    _array_impl(Seq... elements) : _data{elements...} {}
    const T& operator[](std::size_t i) const { return _data[i]; }

    T _data[N];
};


template <class T, std::size_t N>
struct array : _array_impl<T, N>
{
    using _array_impl<T, N>::_array_impl;
};

int main() {
    array<float, 4> a {1, 2, 3, 4};
    for (int i = 0; i < 4; i++)
        std::cout << a[i] << std::endl;
    return 0;
}
template <class... T>
struct type_sequence
{
    static constexpr inline std::size_t size() noexcept { return sizeof...(T); }
};


template <class, class>
struct _concatenate_sequences_impl;
template <class... T, class... U>
struct _concatenate_sequences_impl<type_sequence<T...>, type_sequence<U...>>
    { using type = type_sequence<T..., U...>; };
template <class T, class U>
using concatenate_sequences = typename _concatenate_sequences_impl<T, U>::type;


template <std::size_t N, class T>
struct _repeat_sequence_impl
    { using type = concatenate_sequences<
        typename _repeat_sequence_impl<N/2, T>::type,
        typename _repeat_sequence_impl<N - N/2, T>::type>; };
template <class T>
struct _repeat_sequence_impl<1, T>
    { using type = T; };
template <class... T>
struct _repeat_sequence_impl<0, type_sequence<T...>>
    { using type = type_sequence<>; };
template <std::size_t N, class... T>
using repeat_types = typename _repeat_sequence_impl<N, type_sequence<T...>>::type;