根据特征的存在来推断类型
Deduce type based on existence of a trait
以下repo正试图获取一个std::元组并对其进行迭代,以输出与之相关的各种值。std::tuple是一个顶点,它的最终用途是在元素上调用glEnableVertexArray和glVertexAttribPointer。
到目前为止,我已经迭代了元组的组件类型,并找到了每个元素在每个元组中的偏移量。然而,我被这个功能卡住了:
template<class T>
void EmitAttribute(T const & v, int stride, int offset, int i)
{
std::cout << "Stride is "
<< stride
<< " element index "
<< i
<< " is at offset "
<< offset
<< " has 1 component "
<< std::endl;
}
对于基本类型(非结构化),我想发出"has1 component"。对于具有num_components特性的元素,我希望发出组件的数量。我试过了:
template<class T, class S>
void EmitAttribute(T<S> const & v, int stride, int offset, int i)
{
...
<< " has " << T::num_components << " components "
...
}
但它不会编译。我该如何编写模板,使一个函数在T没有num_components特性时被调用,而另一个函数则在T有num_compomponents特征时被调用?
全额回购:
#include <iostream>
#include <tuple>
template<class T, int C>
struct vec
{
typedef T value_type;
enum { num_components = C };
};
template<class T>
struct vec2 : vec<T, 2>
{
public:
T x, y;
vec2(T X, T Y) : x(X), y(Y) {}
};
template<class T>
struct vec3 : vec<T, 3>
{
public:
T x, y, z;
vec3(T X, T Y, T Z) : x(X), y(Y), z(Z) {}
};
template<class T>
struct vec4 : vec<T, 4>
{
public:
T x, y, z, w;
vec4(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {}
};
namespace VertexAttributes
{
template<class T>
void EmitAttribute(T const & v, int stride, int offset, int i)
{
std::cout << "Stride is "
<< stride
<< " element index "
<< i
<< " is at offset "
<< offset
<< " has 1 component "
<< std::endl;
}
template<int index, class T>
int ElementOffset(T & t)
{
return static_cast<int>(reinterpret_cast<char*>(&std::get<index>(t)) - reinterpret_cast<char*>(&t));
}
template<int index, typename... Ts>
struct Emitter {
void EmitAttributes(std::tuple<Ts...>& t, unsigned size) {
EmitAttribute(std::get<index>(t), size, ElementOffset<index>(t), index);
Emitter <index - 1, Ts...> {}.EmitAttributes(t, size);
}
};
template<typename... Ts>
struct Emitter < 0, Ts... > {
void EmitAttributes(std::tuple<Ts...>& t, unsigned size) {
EmitAttribute(std::get<0>(t), size, ElementOffset<0>(t), 0);
}
};
template<typename... Ts>
void EmitAttributes(std::tuple<Ts...>& t) {
auto const size = std::tuple_size<std::tuple<Ts...>>::value;
Emitter < size - 1, Ts... > {}.EmitAttributes(t, sizeof(std::tuple<Ts...>));
}
}
int main()
{
typedef std::tuple<vec2<float>, vec3<double>, vec4<float>> vertexf;
typedef std::tuple<vec2<double>, vec3<float>, vec4<double>> vertexd;
typedef std::tuple<int, vec3<unsigned>, double> vertexr;
vertexf vf = std::make_tuple(vec2<float>(10, 20), vec3<double>(30, 40, 50), vec4<float>(60, 70, 80, 90));
vertexd vd = std::make_tuple(vec2<double>(10, 20), vec3<float>(30, 40, 50), vec4<double>(60, 70, 80, 90));
vertexr vr = std::make_tuple(100, vec3<unsigned>(110, 120, 130), 140.5);
VertexAttributes::EmitAttributes(vf);
VertexAttributes::EmitAttributes(vd);
VertexAttributes::EmitAttributes(vr);
return 0;
}
您可以创建一个特征
namespace detail
{
template <typename T>
decltype(T::num_components, void(), std::true_type{}) has_num_components_impl(int);
template <typename T>
std::false_type has_num_components_impl(...);
}
template <typename T>
using has_num_components = decltype(detail::has_num_components_impl<T>(0));
然后使用SFINAE或标签调度:
template <typename T>
std::enable_if_t<!has_num_components<T>::value, std::size_t>
get_num_components() { return 1; }
template <typename T>
std::enable_if_t<has_num_components<T>::value, std::size_t>
get_num_components() { return T::num_components; }
最后:
template<class T>
void EmitAttribute(T const & v, int stride, int offset, int i)
{
std::cout << "Stride is "
<< stride
<< " element index "
<< i
<< " is at offset "
<< offset
<< " has "
<< get_num_components<T>()
<< " component "
<< std::endl;
}
实时演示
相关文章:
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数
- 迭代时将指向differents类型的指针保存在std::向量中
- 使用SFINAE来检测void返回类型函数的存在
- 将字符串转换为整数类型T,检查是否存在溢出
- 指向类成员函数的指针中存在类型转换错误
- 输出 [left]=input[i] 行中的 c++ 代码中存在无效的类型错误
- 是否存在 x + 1 == x 类型的浮点型值 x
- 仅当元组中存在该类型时,将功能应用于元组元素
- 使用 SFINAE 检查函数 std::to_string 是否存在类型
- 对条件表达式结果的赋值(其中第二个和第三个操作数是相同类型和值类别的变量)是否仍然存在?
- Clang和GCC在转换C++17中非类型模板参数的自动说明符中存在分歧
- 根据成员变量的类型是否存在,有条件地定义该变量
- 为什么与非类型参数相反,为什么不可见/存在模板类型参数
- C 编译时间检查模板类型中是否存在方法
- 错误:"参数"没有命名类型,.cpp和 .h 文件可能存在问题
- 模板类根据其他类的存在性和优先级以及更多的类型限制(如常量和区分大小写)调用其他类的某些函数
- C 检测是否存在接受特定类型的函数
- 运算符重载:简单添加...错误 C2677:二进制"+":未找到采用类型 ___ 的全局运算符(或者不存在可接受的转换)
- 基于依赖类型存在的重载
- 基于类型存在的模板专用化