bob*_*obo 29 c++ templates sfinae
这是我正在尝试做的事情:
template <typename T> struct Model
{
vector<T> vertices ;
#if T has a .normal member
void transform( Matrix m )
{
each vertex in vertices
{
vertex.pos = m * vertex.pos ;
vertex.normal = m * vertex.normal ;
}
}
#endif
#if T has NO .normal member
void transform( Matrix m )
{
each vertex in vertices
{
vertex.pos = m * vertex.pos ;
}
}
#endif
} ;
Run Code Online (Sandbox Code Playgroud)
我已经看过使用的例子enable_if,但是我无法理解如何应用enable_if这个问题,或者甚至可以应用它.
Joh*_*itb 26
这已成为方式与C++ 11更加容易.
template <typename T> struct Model
{
vector<T> vertices;
void transform( Matrix m )
{
for(auto &&vertex : vertices)
{
vertex.pos = m * vertex.pos;
modifyNormal(vertex, m, special_());
}
}
private:
struct general_ {};
struct special_ : general_ {};
template<typename> struct int_ { typedef int type; };
template<typename Lhs, typename Rhs,
typename int_<decltype(Lhs::normal)>::type = 0>
void modifyNormal(Lhs &&lhs, Rhs &&rhs, special_) {
lhs.normal = rhs * lhs.normal;
}
template<typename Lhs, typename Rhs>
void modifyNormal(Lhs &&lhs, Rhs &&rhs, general_) {
// do nothing
}
};
Run Code Online (Sandbox Code Playgroud)
注意事项:
decltype和sizeof不需要的对象.我知道这个问题已经有了一些答案,但我认为我对这个问题的解决方案有点不同,可以帮助某人。
以下示例检查传递的类型是否包含c_str()函数成员:
template <typename, typename = void>
struct has_c_str : false_type {};
template <typename T>
struct has_c_str<T, void_t<decltype(&T::c_str)>> : std::is_same<char const*, decltype(declval<T>().c_str())>
{};
template <typename StringType,
typename std::enable_if<has_c_str<StringType>::value, StringType>::type* = nullptr>
bool setByString(StringType const& value) {
// use value.c_str()
}
Run Code Online (Sandbox Code Playgroud)
如果需要检查传递的类型是否包含特定的数据成员,可以使用以下方法:
template <typename, typename = void>
struct has_field : std::false_type {};
template <typename T>
struct has_field<T, std::void_t<decltype(T::field)>> : std::is_convertible<decltype(T::field), long>
{};
template <typename T,
typename std::enable_if<has_field<T>::value, T>::type* = nullptr>
void fun(T const& value) {
// use value.field ...
}
Run Code Online (Sandbox Code Playgroud)
更新 C++20
C++20 在这个 C++ 版本中引入了约束和概念,核心语言特性。
如果我们要检查模板参数是否包含c_str成员函数,那么,以下将完成工作:
template<typename T>
concept HasCStr = requires(T t) { t.c_str(); };
template <HasCStr StringType>
void setByString(StringType const& value) {
// use value.c_str()
}
Run Code Online (Sandbox Code Playgroud)
此外,如果我们想检查可转换为 的数据成员是否long存在,可以使用以下方法:
template<typename T>
concept HasField = requires(T t) {
{ t.field } -> std::convertible_to<long>;
};
template <HasField T>
void fun(T const& value) {
// use value.field
}
Run Code Online (Sandbox Code Playgroud)
通过使用 C++20,我们得到了更短、更易读的代码,清楚地表达了它的功能。
| 归档时间: |
|
| 查看次数: |
21409 次 |
| 最近记录: |