gpt4 book ai didi

c++11 - 用 constexpr c++11 填充 N 大小的数组

转载 作者:行者123 更新时间:2023-12-02 23:10:40 24 4
gpt4 key购买 nike

我知道我的代码应该在 c++14 中工作,但我必须在 c++11 中复制此行为,我无法制作等效的 init() 任何人都可以有帮助吗?

enum MyEnum {
BANANA, APPLE, PINEAPPLE, ORANGE, FRUIT_AMOUNT
};

template<MyEnum>
struct Fruit{
virtual ~Fruit(){}
virtual void dostuff(){}
};

template <>
struct Fruit<ORANGE>{
void dostuff(){ cout<<"Hey apple!"<<endl;
}

constexpr array< Fruit*, FRUIT_AMOUNT > init(){
array< Fruit*, FRUIT_AMOUNT > myArray;
for(int i =0; i < FRUIT_AMOUNT; i++)
myArray[i] = new Fruit< (MyEnum) i >();

return myArray;
}

array<Fruit*, FRUIT_AMOUNT> myPrettyFruits = init();

最佳答案

I'm aware that my code should work in c++14

嗯...一点也不。

你的代码有很多问题。

其中一些,排名不分先后

(1) 你不能写

array<Fruit*, FRUIT_AMOUNT>

因为Fruit不是一个类型;这是一个模板类。

例如,Fruit<BANANA>是一种类型,你可以写

std::array<Fruit<BANANA> *, FRUIT_AMOUNT>

但是你不能有指向 Fruit 的指针因为Fruit (不解释模板参数)不是类型。

此问题的可能解决方案是 make all Fruit从公共(public)基础继承的类型;举例说明

struct FruitBase
{ };

template <MyEnum>
struct Fruit : public FruitBase
{
virtual ~Fruit () {}
virtual void dostuff () {}
};

这样你就可以拥有一个 FruitBase 的数组指针

std::array<FruitBase *, FRUIT_AMOUNT>

所以你可以将数组指针放入Fruit<Something>类型也是FruitBase指针。

(2) 你不能拥有

Fruit< (MyEnum) i >

哪里i是运行时已知变量,因为模板参数必须在编译时已知。

一个可能的 C++14 解决方案是使用 std::make_index_sequence获取模板序列(因此编译时已知)std::size_t值。

我建议如下

template <std::size_t ... Is>
constexpr std::array<FruitBase *, FRUIT_AMOUNT>
init_helper (std::index_sequence<Is...> const &)
{ return { { (FruitBase*)(new Fruit<(MyEnum)Is>()) ... } }; }

constexpr std::array<FruitBase *, FRUIT_AMOUNT> init ()
{ return init_helper(std::make_index_sequence<FRUIT_AMOUNT>{}); }

观察两个函数都是一个 return 语句;这对于 constexpr 是必要的C++11 函数。

不幸的是std::index_sequencestd::make_index_sequence仅从 C++14 开始可用。但可以用 C++11 来替代它们。

(3) new Something{}无法在编译时执行

所以你可以定义init_helper() constexpr但这是假的constexpr函数(因此 init() 也是一个假 constexpr 函数),因为无法在编译时执行。

所以你可以写

std::array<FruitBase *, FRUIT_AMOUNT> myPrettyFruits = init();

但是myPrettyFruits运行时初始化。

如果您尝试在编译时初始化它

constexpr std::array<FruitBase *, FRUIT_AMOUNT> myPrettyFruits = init();

您收到编译错误。

下面是一个完整的编译C++11示例,带有 std::index_sequence/std::make_index_sequence替换,仅在运行时有效

#include <array>
#include <iostream>

template <std::size_t...>
struct indexSequence
{ using type = indexSequence; };

template <typename, typename>
struct concatSequences;

template <std::size_t... S1, std::size_t... S2>
struct concatSequences<indexSequence<S1...>, indexSequence<S2...>>
: public indexSequence<S1..., ( sizeof...(S1) + S2 )...>
{ };

template <std::size_t N>
struct makeIndexSequenceH
: public concatSequences<
typename makeIndexSequenceH<(N>>1)>::type,
typename makeIndexSequenceH<N-(N>>1)>::type>::type
{ };

template<>
struct makeIndexSequenceH<0> : public indexSequence<>
{ };

template<>
struct makeIndexSequenceH<1> : public indexSequence<0>
{ };

template <std::size_t N>
using makeIndexSequence = typename makeIndexSequenceH<N>::type;


enum MyEnum
{ BANANA, APPLE, PINEAPPLE, ORANGE, FRUIT_AMOUNT };

struct FruitBase
{ };

template <MyEnum>
struct Fruit : public FruitBase
{
virtual ~Fruit () {}
virtual void dostuff () {}
};

template <>
struct Fruit<ORANGE> : public FruitBase
{ void dostuff () { std::cout << "Hey apple!" << std::endl; } };

// fake constexpr function: new can't be executed compile-time
template <std::size_t ... Is>
constexpr std::array<FruitBase *, FRUIT_AMOUNT>
init_helper (indexSequence<Is...> const &)
{ return { { (FruitBase*)(new Fruit<(MyEnum)Is>()) ... } }; }

// fake constexpr: init_helper() can't be executed compile-time
constexpr std::array<FruitBase *, FRUIT_AMOUNT> init ()
{ return init_helper(makeIndexSequence<FRUIT_AMOUNT>{}); }

int main ()
{
// compile (executed run-time)
std::array<FruitBase *, FRUIT_AMOUNT> myPrettyFruits = init();

// compilation error (init() can't be executed compile-time)
//constexpr std::array<FruitBase *, FRUIT_AMOUNT> myPrettyFruits = init();

}

关于c++11 - 用 constexpr c++11 填充 N 大小的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51754633/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com