- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在设计一个实用程序 header ,用于从 sf::InputStream
中提取二进制数据.为了便于使用,它包含一个函数名称,readFromStream
,它有很多(模板化和非模板化)重载,用于自动反序列化标准布局类型和类型复合,如 vector 、元组和我的定制设计 grid
类(class)。完整的实现可以在这里找到:https://github.com/JoaoBaptMG/ReboundTheGame/blob/master/MainGame/utility/streamCommons.hpp
所以,我定义了一个重载 readFromStream
通过调用 readFromStream
抽出任何类型的 vector 再次递归:
template <typename T, typename std::enable_if<!is_optimization_viable<T>::value, int>::type = 0>
bool readFromStream(sf::InputStream &stream, std::vector<T> &value)
{
size_t size;
if (!readFromStream(stream, VarLength(size)))
return false;
std::vector<T> newVal(size, T());
for (auto &val : newVal)
if (!readFromStream(stream, val))
return false;
newVal.swap(value);
return true;
}
我想为标准布局类编写一个优化版本因为readFromStream
没有重载,因此我们可以利用它们的内存布局并将它们写入单个 read
中调用:
// trait is_optimization_viable is what I'm having trouble to write
template <typename T, typename std::enable_if<is_optimization_viable<T>::value, int>::type = 0>
bool readFromStream(sf::InputStream &stream, std::vector<T> &value)
{
size_t size;
if (!readFromStream(stream, VarLength(size)))
return false;
std::vector<T> newVal(size, T());
if (stream.read(newVal.data(), size*sizeof(T)) != size*sizeof(T))
return false;
newVal.swap(value);
return true;
}
好吧,我可以使用其他答案中描述的解决方案来检测函数的存在,但有一个问题。当类型是标准布局时,我有一个默认值 readFromStream
内容如下:
template <typename T, typename std::enable_if<std::is_standard_layout<T>::value, int>::type = 0>
bool readFromStream(sf::InputStream &stream, T& value)
{
return stream.read((void*)&value, sizeof(T)) == sizeof(T);
}
所以,总有一个函数可以执行序列化,而不仅仅是我想要的那个。我想在这里解决的问题是:如何检测非默认 readFromString
的存在?对于类型 T
, 为了禁用 readFromString
的优化版本对于 std::vector<T>
?
我尝试了一些技巧。我不能将优化限制为 POD 类型,因为我使用的是 sf::Vector2<T>
在某些我想反序列化的类型上,这不是 POD。我尝试比较使用非模板化函数和模板化函数时获得的函数地址,例如:
using FPtr = bool(*)(sf::InputStream&, T&);
return (FPtr)readFromStream == (FPtr)readFromStream<T>;
但是,奇怪的是,它没有用。我研究了很多解决方案,但没有一个可以适应我的需要。也许这在 C++ 中是不可能的,我将不得不求助于“标记”我不想优化的类型。或者它可能是一些我没想到的晦涩模板。我怎么能这样做?
最佳答案
据我了解,您的问题是:
is_optimization_viable<T>;
可以定义为:
template<typename T>
using is_optimization_viable<T> = std::is_standard_layout<T>;
但事实上,对于 T
的某些值是标准布局你仍然需要自定义 bool readFromStream(sf::InputStream &stream, T &value)
,过载,这意味着它们不优化可行。
既然您必须编写这些自定义重载,那么您知道那些T
的异常值是。假设它们是类型 X
, Y
, Z
.然后您可以将特征定义为:
#include <type_traits>
template<typename T, typename ...Us>
struct is_one_of;
template<typename T>
struct is_one_of<T> {
static constexpr bool value = false;
};
template<typename T, typename First, typename ...Rest>
struct is_one_of<T,First,Rest...> {
static constexpr bool value =
std::is_same<T,First>::value || is_one_of<T,Rest...>::value;
};
// ^ C++17: `std::disjunction` does the job
template<typename T>
using has_custom_read_from_stream = is_one_of<T,X,Y,Z>;
template<typename T>
struct is_optimization_viable {
static constexpr bool value = std::is_standard_layout<T>::value &&
!has_custom_read_from_stream<T>::value;
};
感谢您宁愿避免持续维护硬编码类型列表 X
, Y
, Z
, 并且更喜欢 SFINAE-probe是否来电readFromStream(s, t)
将调用其中一个一些 std::declval
-ed 的自定义重载s
和 t
.
但这只是海市蜃楼。你告诉我们,会有一些过载 readFromStream(s, t)
这将编译任何类型的 t
.如果是这样,SFINAE 探测器将始终告诉您是的, readFromStream(s, t)
将编译 - 对于任何 T
作为 t
的不合格类型.你呢仍然必须就是否 T
做出编译时决定是其中之一自定义类型,如果不是,是否是标准布局。
这就是问题所在。判断是否T
是其中之一自定义类型,您必须测试它与任何一个的身份如图所示,它们是分离的,或者你必须找到一个独立于它们的特征满足所有且仅自定义类型的身份。如你不要告诉我们那些自定义类型是什么,我不能建议任何这样的特征,但是如果你找到一个,那么它将定义或替换has_custom_read_from_stream<T>
.
顺便说一句,我支持@NirFriedman 的评论:是std::standard_layout
你真的是这个意思吗?
关于c++ - 当模板重载可用时,检查函数的自定义重载是否存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43711573/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!