class 成员是否可以根据 c++ 中的模板参数进行更改
Can the class member can be changed depending on the template args in c++
我希望 class 成员可以根据模板参数进行更改。
我想要像 follow
这样的东西
template<int value>
class MyClass
{
public:
void print()
{
// using the member
std::cout << sizeData() << std::endl;
for (int i=0;i<sizeData();i++)
{
std:cout << data[i] << std::endl;
}
}
static int sizeData()
{
#if value == 1
return 3;
#endif
#if value == 2
return 6;
#endif
}
static int sizeArray()
{
#if value == 1
return 40;
#endif
#if value == 2
return 200;
#endif
}
private:
#if value == 1
int data[3];
const static int array[40];
#endif
#if value == 2
int data[6];
const static int array[200];
#endif
}
不知道c++能不能实现
感谢您的宝贵时间。
添加
很多sir已经在C++11和C++17中给出了答案。谢谢大家的指点。
如果代码能在C++98中落户就完美了。因为我的代码应该 运行 在只支持 C++98 的平台上。
不,这不能用 c++ 实现。可以通过运行时变量评估预编译器“if”。
您可以声明一个 std::vector
来解决这个问题。通过这种方式,您可以使用作为参数传递的值对其进行初始化。
此时size数组和size数据函数不需要预编译器"if",只需要一个简单的if-else语句。
从 C++17 开始,您可以使用 constexpr if
template<int value>
class MyClass
{
public:
MyClass() : data() {}
static constexpr int sizeData() {
if constexpr (value == 1) { return 3; }
else if constexpr (value == 2) { return 6; }
else { return 1; } // default value is '1'
}
static constexpr int sizeArray() {
if constexpr (value == 1) { return 40; }
else if constexpr (value == 2) { return 200; }
else { return 10; } // default value is '10'
}
private:
int data[sizeData()];
const static int array[sizeArray()];
};
如果使用例如C++14,您可以实现自定义值特征,在编译时将给定的 int
值映射到另一个命名 (int
) 常量,并在 class 中使用这些值特征模板:
template<int value>
constexpr int ValueToDataSizeMapping = 1; // default is '1'
template<>
constexpr int ValueToDataSizeMapping<1> = 3;
template<>
constexpr int ValueToDataSizeMapping<2> = 6;
template<int value>
constexpr int ValueToArraySizeMapping = 10; // default is '10'
template<>
constexpr int ValueToArraySizeMapping<1> = 40;
template<>
constexpr int ValueToArraySizeMapping<2> = 200;
template<int value>
class MyClass
{
public:
MyClass() : data() {}
private:
int data[ValueToDataSizeMapping<value>];
const static int array[ValueToArraySizeMapping<value>];
};
您可以使用std::conditional
来选择您想要喜欢的成员
template<int value>
class MyClass
{
public:
static int sizeData()
{
return (value == 1) ? 3 : 6; // needs to be improved
}
static int sizeArray()
{
return sizeof(array) / sizeof(array[0]); // size of array divided by size of element is then number of elements in the array
}
private:
std::conditional_t<value == 1, int[3], int[6]> data;
const static std::conditional_t<value == 1, int[40], int[200]> array;
};
虽然 std::conditional
不是 C++98 的一部分,但它仅使用 C++98 C++ 实现,因此您可以使用参考站点 link 中可能的实现来实现自己的想法.你可以看到使用
#include <iostream>
template<bool B, class T, class F>
struct conditional { typedef T type; };
template<class T, class F>
struct conditional<false, T, F> { typedef F type; };
template<int value>
class MyClass
{
public:
static int sizeData()
{
return (value == 1) ? 3 : 6; // needs to be improved
}
static int sizeArray()
{
return sizeof(array) / sizeof(array[0]);
}
private:
typename conditional<value == 1, int[3], int[6]>::type data;
const static typename conditional<value == 1, int[40], int[200]>::type array;
};
int main()
{
MyClass<1> m;
std::cout << m.sizeData();
}
在这个live example.
对于 sizeData
这种情况会分崩离析,因为 data
不是 static
但函数是。为了避免代码重复,我们可以使用枚举技巧来获取数组大小的编译时间常量,而不是使用 std::conditional
,并像
这样使用它
#include <iostream>
template<int value>
class MyClass
{
public:
static int sizeData()
{
return data_size; // now improved
}
static int sizeArray()
{
return array_size;
}
private:
enum { data_size = (value == 1) ? 3 : 6 }; // this is required to be a compile time constant
enum { array_size = (value == 1) ? 40 : 200 }; // these need to become before the array members
int data[data_size]; // less verbose
const static int array[array_size];
};
int main()
{
MyClass<1> m;
std::cout << m.sizeData();
}
您需要将条件逻辑移动到本地化的地方。 static inline constexpr
变量是你的朋友,如果 C++17 是一个选项:
template<int value>
class MyClass
{
private:
inline static constexpr int data_size = (value == 1) ? 3 : 6;
inline static constexpr int array_size = (value == 1) ? 40 : 200;
public:
static int sizeData() { return data_size; }
static int sizeArray() {return array_size; }
private:
int data[data_size];
const static int array[array_size];
};
如果计算大小的逻辑需要更复杂,您总是可以编写一个 constexpr
函数来计算它,给定一个 value
作为 (non-template) 参数。
既然你处理的是 C++98 那么你必须使用 template specialization:
template<int value>
class MyClass
{
};
template<>
class MyClass<1>
{
public:
int sizeData()
{
return 3;
}
int sizeArray()
{
return 40;
}
private:
int data[3];
const static int array[40];
};
template<>
class MyClass<2>
{
public:
int sizeData()
{
return 6;
}
int sizeArray()
{
return 200;
}
private:
int data[6];
const static int array[200];
};
template<int value>
class Child : public MyClass<value>
{
public:
int calc()
{
// will only work and compile for value 1, 2
return this->sizeData() + this->sizeArray();
}
};
您可以使用 if constexpr
并立即评估 constexpr lambdas
。
免责声明:它只是 C++ 17,需要额外的括号将 lambda 括起来以便编译,我真的不建议按原样使用此代码。它的用途是 仅供演示!
template<int value>
class MyClass
{
public:
static int sizeData()
{
if constexpr(value == 1)
return 3;
if constexpr (value == 2)
return 6;
}
static int sizeArray()
{
if constexpr (value == 1)
return 40;
if constexpr (value == 2)
return 200;
}
private:
int data[([](int v) constexpr { if (v == 1) return 3; if (v==2) return 6; }(value))];
const static int array[([](int v) constexpr { if (v == 1) return 40; if (v==2) return 200; }(value))];
};
int main()
{
MyClass<1> m1;
MyClass<2> m2;
}
我希望 class 成员可以根据模板参数进行更改。 我想要像 follow
这样的东西template<int value>
class MyClass
{
public:
void print()
{
// using the member
std::cout << sizeData() << std::endl;
for (int i=0;i<sizeData();i++)
{
std:cout << data[i] << std::endl;
}
}
static int sizeData()
{
#if value == 1
return 3;
#endif
#if value == 2
return 6;
#endif
}
static int sizeArray()
{
#if value == 1
return 40;
#endif
#if value == 2
return 200;
#endif
}
private:
#if value == 1
int data[3];
const static int array[40];
#endif
#if value == 2
int data[6];
const static int array[200];
#endif
}
不知道c++能不能实现
感谢您的宝贵时间。
添加
很多sir已经在C++11和C++17中给出了答案。谢谢大家的指点。
如果代码能在C++98中落户就完美了。因为我的代码应该 运行 在只支持 C++98 的平台上。
不,这不能用 c++ 实现。可以通过运行时变量评估预编译器“if”。
您可以声明一个 std::vector
来解决这个问题。通过这种方式,您可以使用作为参数传递的值对其进行初始化。
此时size数组和size数据函数不需要预编译器"if",只需要一个简单的if-else语句。
从 C++17 开始,您可以使用 constexpr if
template<int value>
class MyClass
{
public:
MyClass() : data() {}
static constexpr int sizeData() {
if constexpr (value == 1) { return 3; }
else if constexpr (value == 2) { return 6; }
else { return 1; } // default value is '1'
}
static constexpr int sizeArray() {
if constexpr (value == 1) { return 40; }
else if constexpr (value == 2) { return 200; }
else { return 10; } // default value is '10'
}
private:
int data[sizeData()];
const static int array[sizeArray()];
};
如果使用例如C++14,您可以实现自定义值特征,在编译时将给定的 int
值映射到另一个命名 (int
) 常量,并在 class 中使用这些值特征模板:
template<int value>
constexpr int ValueToDataSizeMapping = 1; // default is '1'
template<>
constexpr int ValueToDataSizeMapping<1> = 3;
template<>
constexpr int ValueToDataSizeMapping<2> = 6;
template<int value>
constexpr int ValueToArraySizeMapping = 10; // default is '10'
template<>
constexpr int ValueToArraySizeMapping<1> = 40;
template<>
constexpr int ValueToArraySizeMapping<2> = 200;
template<int value>
class MyClass
{
public:
MyClass() : data() {}
private:
int data[ValueToDataSizeMapping<value>];
const static int array[ValueToArraySizeMapping<value>];
};
您可以使用std::conditional
来选择您想要喜欢的成员
template<int value>
class MyClass
{
public:
static int sizeData()
{
return (value == 1) ? 3 : 6; // needs to be improved
}
static int sizeArray()
{
return sizeof(array) / sizeof(array[0]); // size of array divided by size of element is then number of elements in the array
}
private:
std::conditional_t<value == 1, int[3], int[6]> data;
const static std::conditional_t<value == 1, int[40], int[200]> array;
};
虽然 std::conditional
不是 C++98 的一部分,但它仅使用 C++98 C++ 实现,因此您可以使用参考站点 link 中可能的实现来实现自己的想法.你可以看到使用
#include <iostream>
template<bool B, class T, class F>
struct conditional { typedef T type; };
template<class T, class F>
struct conditional<false, T, F> { typedef F type; };
template<int value>
class MyClass
{
public:
static int sizeData()
{
return (value == 1) ? 3 : 6; // needs to be improved
}
static int sizeArray()
{
return sizeof(array) / sizeof(array[0]);
}
private:
typename conditional<value == 1, int[3], int[6]>::type data;
const static typename conditional<value == 1, int[40], int[200]>::type array;
};
int main()
{
MyClass<1> m;
std::cout << m.sizeData();
}
在这个live example.
对于 sizeData
这种情况会分崩离析,因为 data
不是 static
但函数是。为了避免代码重复,我们可以使用枚举技巧来获取数组大小的编译时间常量,而不是使用 std::conditional
,并像
#include <iostream>
template<int value>
class MyClass
{
public:
static int sizeData()
{
return data_size; // now improved
}
static int sizeArray()
{
return array_size;
}
private:
enum { data_size = (value == 1) ? 3 : 6 }; // this is required to be a compile time constant
enum { array_size = (value == 1) ? 40 : 200 }; // these need to become before the array members
int data[data_size]; // less verbose
const static int array[array_size];
};
int main()
{
MyClass<1> m;
std::cout << m.sizeData();
}
您需要将条件逻辑移动到本地化的地方。 static inline constexpr
变量是你的朋友,如果 C++17 是一个选项:
template<int value>
class MyClass
{
private:
inline static constexpr int data_size = (value == 1) ? 3 : 6;
inline static constexpr int array_size = (value == 1) ? 40 : 200;
public:
static int sizeData() { return data_size; }
static int sizeArray() {return array_size; }
private:
int data[data_size];
const static int array[array_size];
};
如果计算大小的逻辑需要更复杂,您总是可以编写一个 constexpr
函数来计算它,给定一个 value
作为 (non-template) 参数。
既然你处理的是 C++98 那么你必须使用 template specialization:
template<int value>
class MyClass
{
};
template<>
class MyClass<1>
{
public:
int sizeData()
{
return 3;
}
int sizeArray()
{
return 40;
}
private:
int data[3];
const static int array[40];
};
template<>
class MyClass<2>
{
public:
int sizeData()
{
return 6;
}
int sizeArray()
{
return 200;
}
private:
int data[6];
const static int array[200];
};
template<int value>
class Child : public MyClass<value>
{
public:
int calc()
{
// will only work and compile for value 1, 2
return this->sizeData() + this->sizeArray();
}
};
您可以使用 if constexpr
并立即评估 constexpr lambdas
。
免责声明:它只是 C++ 17,需要额外的括号将 lambda 括起来以便编译,我真的不建议按原样使用此代码。它的用途是 仅供演示!
template<int value>
class MyClass
{
public:
static int sizeData()
{
if constexpr(value == 1)
return 3;
if constexpr (value == 2)
return 6;
}
static int sizeArray()
{
if constexpr (value == 1)
return 40;
if constexpr (value == 2)
return 200;
}
private:
int data[([](int v) constexpr { if (v == 1) return 3; if (v==2) return 6; }(value))];
const static int array[([](int v) constexpr { if (v == 1) return 40; if (v==2) return 200; }(value))];
};
int main()
{
MyClass<1> m1;
MyClass<2> m2;
}