C++ 用SFINAE计算不同单元的尺寸 介绍
我刚刚开始阅读和研究SFINAE。为了提高我的理解力,我开始自己尝试 所以我一直在想一个有用但简单的方法来使用SFINAE强大的技巧,最后我想到了一组函数来计算一个给定类型占用了多少字节;只要我们处理简单类型,解决方案就很简单:C++ 用SFINAE计算不同单元的尺寸 介绍,c++,templates,metaprogramming,sfinae,C++,Templates,Metaprogramming,Sfinae,我刚刚开始阅读和研究SFINAE。为了提高我的理解力,我开始自己尝试 所以我一直在想一个有用但简单的方法来使用SFINAE强大的技巧,最后我想到了一组函数来计算一个给定类型占用了多少字节;只要我们处理简单类型,解决方案就很简单: template <typename T> size_t SizeOf(const T &t) { return sizeof(T); }; 是的,在这一点上,似乎根本不需要SFINAE,但是,让我们想想容器。容器的SizeOf必须是Siz
template <typename T> size_t SizeOf(const T &t)
{
return sizeof(T);
};
是的,在这一点上,似乎根本不需要SFINAE,但是,让我们想想容器。容器的SizeOf
必须是SizeOf(容器类型)
加上每个元素的大小之和,SFINAE在此输入:
template <typename T> size_t SizeOf(const T &t)
{
size_t Result = sizeof(t);
for (T::const_iterator i = t.begin(); i != t.end(); ++i)
{
Result += SizeOf(*i);
}
return Result;
};
上述代码生成此输出:
1: 4
5: 45
6: 58
7: 66
8: 20
is_指针
specialization,而输出3和4将使用is_数组
1。嗯,我错了,但我不知道为什么std::basic_string
doSizeOf(container)+SizeOf(container::value\u type)*container.size()中,迭代所有项目并为每个项目调用SizeOf
是一个不错的选择,但并非所有容器都如此
会更快,但我无法了解如何专门处理基本字符串
true\u类型
和false\u类型
typedef
s是一种常见的做法,通常定义为char
和char[2]
;但我发现一些作者使用char
和long
作为true\u类型
和false\u类型
有人知道哪一个是最佳实践还是最标准的实践请注意,我不是在寻找为什么不尝试“此库”或“此工具”之类的答案,我的目标是练习和理解SFINAE,任何线索和建议都是好的。1.您应该阅读C++11中的POD概念。POD类型元素数组或指向POD类型元素的指针都是POD类型 例如,下面的代码可以很好地编译 2.像这样的东西可以帮你
template<typename T>
struct is_string
{
enum
{
value = false
};
};
template<typename Char, typename Traits, typename Alloc>
struct is_string<std::basic_string<Char, Traits, Alloc>>
{
enum
{
value = true
};
};
模板
结构是字符串
{
枚举
{
值=假
};
};
模板
结构是字符串
{
枚举
{
值=真
};
};
功能
// Iterable class specialization.
template <typename T> typename std::enable_if<is_iterable<T>::value && !is_string<T>::value, size_t>::type SizeOf(const T &aValue)
{
size_t Result = sizeof(aValue);
for (typename T::const_iterator I = aValue.begin(); I != aValue.end(); ++I)
{
Result += SizeOf(*I);
}
return Result;
}
template <typename T> typename std::enable_if<is_string<T>::value, size_t>::type SizeOf(const T& aValue)
{
return sizeof(aValue) + sizeof(typename T::value_type) * aValue.length();
}
//Iterable类专门化。
模板typename std::enable_if::type SizeOf(const T&aValue)
{
大小\u t结果=sizeof(aValue);
for(typename T::const_迭代器I=aValue.begin();I!=aValue.end();++I)
{
结果+=尺寸(*I);
}
返回结果;
}
模板typename std::enable_if::type SizeOf(const T&aValue)
{
返回sizeof(aValue)+sizeof(typename T::value_type)*aValue.length();
}
3.标准中没有这样的信息,sizeof(long)
永远不应该等于sizeof(char)
,但是sizeof(char)
不能等于sizeof(char[2])
,所以我认为第二种变体更可取。关于问题3,我认为在C++11中,它更干净(更清晰)使用而不是sizeof
来获取诸如std::true\u type
和std::false\u type
之类的
例如,您的是可编辑的
:
#include <type_traits> // std::true_type, std::false_type
// Iterable class detector
template <typename T> class is_iterable {
template <typename U> static std::true_type test(typename U::const_iterator *);
template <typename U> static std::false_type test(...);
public:
// Using decltype in separate typedef because of gcc 4.6 bug:
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=6709
typedef decltype(test<T>(0)) result_type;
static const bool value = result_type::value;
};
#包括//std::true\u类型、std::false\u类型
//可调类检测器
模板类是不可编辑的{
模板静态std::true_类型测试(typename U::const_iterator*);
模板静态标准::假_型测试(…);
公众:
//由于gcc 4.6错误,在单独的typedef中使用decltype:
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=6709
typedef decltype(测试(0))结果类型;
静态常量布尔值=结果类型::值;
};
container.size()
char[2]
是首选,因为根据标准,sizeof(long)
可以是1template<typename T, unsigned N>
constexpr size_t SizeOf(const T (&aValue)[N])
{
// return N * sizeof(T); If you want to do the work yourself
return sizeof(aValue); // But why bother?
}
模板
constexpr size\u t SizeOf(const&aValue)[N])
{
//返回N*sizeof(T);如果您想自己做这项工作
return sizeof(aValue);//但是为什么要麻烦呢?
}
1)。因为数组名-它是指向第一个单元格的指针。它们被认为是指针。所以你有一个模棱两可的电话。我建议您对指针使用另一个版本的重载SizeOf
。使用sizeof(\u-array)/sizeof(\u-array[0])计算数组大小更好。
。2). 在这种情况下,应使用模板参数作为模板。例如:template std::enable_if::type SizeOf(const T&\u value)
在其中可以声明变量容器
。它将专门用于std::basic_string.3)。没有区别,因为long和char的大小不同(我希望在所有编译器中都是如此)。@Pie_Jesu:不,数组名不是指向其第一个元素的指针。信息技术
#include <type_traits> // std::true_type, std::false_type
// Iterable class detector
template <typename T> class is_iterable {
template <typename U> static std::true_type test(typename U::const_iterator *);
template <typename U> static std::false_type test(...);
public:
// Using decltype in separate typedef because of gcc 4.6 bug:
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=6709
typedef decltype(test<T>(0)) result_type;
static const bool value = result_type::value;
};
template<typename T, unsigned N>
constexpr size_t SizeOf(const T (&aValue)[N])
{
// return N * sizeof(T); If you want to do the work yourself
return sizeof(aValue); // But why bother?
}