我想要一个结构模板,该结构模板由在构造过程中传递给它的组件的特定值定义,这样,不同的值将创建不同的C ++数据类型,并且认为非类型模板参数可能对此有用。 这样的事情(只是一个简单的例子来说明问题,实际的结构会更复杂):
enum ElementType
{
TYPE1,
TYPE2
};
template<ElementType elementType, int size>
struct DataType
{
DataType(ElementType et = elementType, int s = size):
elementType_(et),
size_(s)
{
}
ElementType elementType_;
int size_;
};
int main()
{
auto d1 = DataType(ElementType::TYPE1, 1);
}
我尝试使用g ++-8 -std = c ++ 17构建它,它给我以下错误:
./main.cpp:23:42: error: class template argument deduction failed:
auto d1 = DataType(ElementType::TYPE1, 1);
^
../main.cpp:23:42: error: no matching function for call to ‘DataType(ElementType, int)’
../main.cpp:12:2: note: candidate: ‘template<ElementType elementType, int size> DataType(ElementType, int)-> DataType<elementType, size>’
DataType(ElementType et = elementType, int s = size):
^~~~~~~~
../main.cpp:12:2: note: template argument deduction/substitution failed:
../main.cpp:23:42: note: couldn't deduce template parameter ‘elementType’
auto d1 = DataType(ElementType::TYPE1, 1);
^
../main.cpp:23:42: error: expression list treated as compound expression in functional cast [-fpermissive]
../main.cpp:23:42: warning: left operand of comma operator has no effect [-Wunused-value]
请注意,我无法使用类型模板参数,因为两种类型的参数是固定的(ElementType
和int
),但是DataType(ElementType::TYPE1, 1)
的类型必须与{{1 }}和DataType(ElementType::TYPE1, 2)
必须与DataType(ElementType::TYPE1, 1)
不同。
答案 0 :(得分:4)
您可以这样定义模板:
template<ElementType elementType, int size>
struct DataType
{
const ElementType elementType_ = elementType;
const int size_ = size;
};
并创建一个这样的实例:
auto d1 = DataType<ElementType::TYPE1, 1>();
答案 1 :(得分:1)
要利用推论,您传递给构造函数的值必须是一个常量表达式。不幸的是,作为参数传递的值失去了constexpr属性。为了防止这种行为,您可以传递包装在类型中的值,例如使用std::integral_constant
。
示例用法:
#include <type_traits>
enum ElementType
{
TYPE1,
TYPE2
};
template<ElementType elementType, int size>
struct DataType
{
DataType(std::integral_constant<ElementType, elementType>, std::integral_constant<int, size> ic):
elementType_(elementType),
size_(ic)
{
}
ElementType elementType_;
int size_;
};
int main()
{
auto d1 = DataType(std::integral_constant<ElementType, TYPE1>{}, std::integral_constant<int, 1>{});
}
要使其更方便使用,您可以使用constexpr后缀运算符将整数const包裹起来:
#include <type_traits>
enum ElementType
{
TYPE1,
TYPE2
};
template <class... Ts>
constexpr int ival(Ts... Vs) {
char vals[sizeof...(Vs)] = {Vs...};
int result = 0;
for (int i = 0; i < sizeof...(Vs); i++) {
result *= 10;
result += vals[i] - '0';
}
return result;
}
template <class T, class... Ts>
constexpr ElementType etval(T V, Ts... Vs) {
if (V == '1')
return TYPE1;
if (V == '2')
return TYPE2;
}
template <char... Vs>
std::integral_constant<int, ival(Vs...)> operator""_i() {
return {};
}
template <char... Vs>
std::integral_constant<ElementType, etval(Vs...)> operator""_et() {
return {};
}
template<ElementType elementType, int size>
struct DataType
{
DataType(std::integral_constant<ElementType, elementType>, std::integral_constant<int, size> ic):
elementType_(elementType),
size_(ic)
{
}
ElementType elementType_;
int size_;
};
int main()
{
auto d1 = DataType(1_et, 1_i);
}