我有一个traits类,它通过推导成员函数的类型来定义"范围"(或容器,序列)的类型,如下所示:
template<class R>
struct range_type_traits
{
// "iterator": The type of the iterators of a range
using iterator = decltype(std::begin(std::declval<R>()));
// "value_type": The (non-reference) type of the values of a range
using value_type = typename std::remove_reference<decltype(*(std::declval<iterator>()))>::type;
};
Run Code Online (Sandbox Code Playgroud)
我这样做的原因(并没有R直接或使用子类型std::iterator_traits)是支持某个模板化库中具有begin()成员的任何类型的容器,并且不要求容器定义了一些value_type/ iterator类型.据我所知,std::iterator_traits无法处理某些容器的"密钥类型",这些容器不会使用对象将其迭代器接口暴露给STL,例如std::map:(例如:QMap<K,T>has value_type = T.您可以通过iterator::key().访问密钥.).
现在我想有条件地定义一个类型key_type,如果iterator有一个函数::key() const并采用它的返回类型,类似于我用它做的value_type.如果我只是将定义放在现有的traits类中,那么对于不支持此类的容器,编译就会失败.
SFINAE std::enable_if可以有条件地启用模板功能.如何有条件地扩展现有类/有条件地定义子类型?
像这样的草图:
template<class R>
struct range_type_traits
{
// …Run Code Online (Sandbox Code Playgroud) 为了使用SFINAE t对类型参数进行区分T,我想知道该语句
QVariant::fromValue(t);
Run Code Online (Sandbox Code Playgroud)
和/或
QVariant::value<T>();
Run Code Online (Sandbox Code Playgroud)
编译.如果一个编译,另一个编译,除非你破解元类型系统.当且仅当T声明已使用时,它们才会编译Q_DECLARE_METATYPE(T).
非常简单的用法示例,其中一个人想要通过简单地qDebugging一个变量包装的等价物来打印一个值的类型,当且仅当元类型系统支持时(我不需要这个,但这显示了一个最小的问题)例):
template<class T> // enable if T NOT registered in the Qt meta type system
void print(const T &t) {
qDebug() << t;
}
template<class T> // enable if T registered in the Qt meta type system
void print(const T &t) {
qDebug() << QVariant::fromValue<T>();
}
Run Code Online (Sandbox Code Playgroud)
我知道有几种(但类似的)可能性,但它们都引入了一些辅助结构,复杂的enable_if等等.现在我知道有QTypeInfo哪些,我想,已经提供了类似于"在Qt元类型系统中声明的东西" "类型特征.但是,此类未记录,因此不建议在长期和高效代码中使用,因为它可能在Qt版本之间发生变化.
如果TQVariant支持某种类型,是否有一种非常简单的方法(比使用"checker"+ enable_if更简单)来检查SFINAE专业化?
请注意,解决方案仍应在不同Qt版本之间移植(Qt4和Qt5可能使用不同的QTypeInfo定义).但是,我使用C++ 11,所以我可以访问std::enable_if例如.
"非便携式"的方法是使用的内部定义QMetaTypeId2<T>::Defined在一个enable_if(它是或1定义为0的枚举值).因此,一个有效的解决方案是: …
似乎很难找到有关如何在连续渲染过程的着色器中访问深度和模板缓冲区的信息.
在第一个渲染过程中,我不仅渲染颜色和深度信息,还使用模板操作来计算对象.我为此使用了一个多渲染目标FBO,附带了颜色缓冲区和组合深度模板缓冲区.所有这些都是纹理的形式(没有涉及渲染缓冲对象).
在第二个渲染过程中(当渲染到屏幕时),我想基于每个像素访问先前计算的模板索引(但不一定是我正在绘制的相同像素),类似于您想要访问的先前渲染的颜色缓冲区以应用一些后期处理效果.
但是我没能将第二遍中的深度模板纹理绑定到我的着色器程序作为制服.至少只从中读取黑色值,所以我猜它没有正确绑定.
是否可以将深度模板纹理绑定到纹理单元以用于着色器程序?使用"普通"采样器是否无法访问深度和模板纹理?是否可以使用一些"特殊"采样器?它取决于在纹理或类似设置上设置的插值模式吗?
如果没有,在这两个渲染过程之间将模板信息复制到单独的颜色纹理中的最佳(最快)方法是什么?可能涉及使用模板测试绘制单一颜色的第三个渲染过程(我在最终渲染过程中只需要模板缓冲区的二进制版本,确切地说,我需要测试值是否为零).
中间FBO使用的纹理设置如下:
// The textures for color information (GL_COLOR_ATTACHMENT*):
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// The texture for depth and stencil information (GL_DEPTH_STENCIL_ATTACHMENT*):
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
Run Code Online (Sandbox Code Playgroud)
在第二个渲染过程中,我目前只尝试"调试"所有纹理的内容.因此,我使用以下值设置着色器:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, <texture>);
glUniform1i(texLocation, 0);
Run Code Online (Sandbox Code Playgroud)
让着色器程序只需将纹理复制到屏幕:
uniform sampler2D tex;
in vec2 texCoord;
out vec4 fragColor;
void main() {
fragColor = texture2D(tex, texCoord);
}
Run Code Online (Sandbox Code Playgroud)
结果如下:
当<texture>上面指的是我的一个颜色纹理时,我看到在第一个渲染过程中渲染的颜色输出,这是我所期望的.
当<texture>上面指深度模板纹理时,着色器不做任何事情(我看到用于清除屏幕的颜色).
将深度模板纹理复制到CPU并进行检查时,我会按预期在打包的24 + 8位数据中看到深度和模板信息.
如果只定义此方法,则会出现编译错误.
void classA::testMethod() {
}
Run Code Online (Sandbox Code Playgroud)
所以必须先声明:
class classA {
void testMethod();
};
Run Code Online (Sandbox Code Playgroud)
为什么要宣布这些?
我知道对于常见的C方法方法,它不需要声明,但它们只能被定义:
void test() {
}
Run Code Online (Sandbox Code Playgroud) 当我将lambda分配给显式类型变量时(例如,当它是递归的时,为了捕获函数本身),我使用std::function.
以这个愚蠢的"位计数"函数为例:
std::function<int(int)> f;
f = [&f](int x){ return x ? f(x/2)+1 : 0; };
Run Code Online (Sandbox Code Playgroud)
当我们使用auto参数进行泛化时x,如C++ 14泛型lambda中所介绍的情况怎么样?
std::function<int(???)> f;
f = [&f](auto x){ return x ? f(x/2)+1 : 0; };
Run Code Online (Sandbox Code Playgroud)
很显然,我不能把auto在function类型参数.
是否有可能通常定义一个仿函数类来覆盖上面的确切情况,但仍然使用lambda作为函数定义?
(不要过度概括这一点,只接受一个自动参数并对返回值进行硬编码.)用例适用于上述场景:通过引用为递归调用捕获函数本身.
我有一个针对iOS和Android的Xamarin项目。我主要在Windows上使用Visual Studio开发。该项目是由git版本控制的。
最近,我使用Mac来构建和部署iOS应用,为此,我在下方添加了图标集(应用图标和启动屏幕)Resources/Media.xcassets。将这些更改提交到git并将其拉到Windows计算机上之后,并打开Visual Studio之后,该Resources/Media.xcassets条目不会显示在解决方案资源管理器中。
从本质上讲,这不是问题,但是csprojVS修改了文件,如下所示(因此,基本上将图像资产标记为不可见):
<ItemGroup>
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Contents.json" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-20x20@1x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-20x20@2x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-20x20@3x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-29x29@1x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-29x29@2x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-29x29@3x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-40x40@1x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-40x40@2x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-40x40@3x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-60x60@2x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-60x60@3x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-76x76@1x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-76x76@2x.png" />
- <ImageAsset Include="Resources\Media.xcassets\AppIcon.appiconset\Icon-App-83.5x83.5@2x.png" />
- <ImageAsset Include="Resources\Media.xcassets\LaunchImage.launchimage\Contents.json" />
- <ImageAsset Include="Resources\Media.xcassets\LaunchImage.launchimage\Default.png" /> …Run Code Online (Sandbox Code Playgroud) 我想在类的构造函数中为functor参数设置一个默认仿函数.作为一个最小的例子,我提出了一个应该作为过滤器服务器的类,它过滤Tiif 类型的元素,过滤器函数返回true.过滤器函数应该在构造函数中提供,默认为"accept all"过滤器函数:
template<class T>
class Filter
{
public:
typedef std::function<bool(const T&)> FilterFunc;
Filter(const FilterFunc & f = [](const T&){ return true; }) :
f(f)
{
}
private:
FilterFunc f;
};
Run Code Online (Sandbox Code Playgroud)
我实例化模板类,如下所示:
int main() {
Filter<int> someInstance; // No filter function provided (<-- line 19)
}
Run Code Online (Sandbox Code Playgroud)
但是,gcc 4.7似乎不喜欢这段代码:
prog.cpp: In constructor ‘Filter<T>::Filter(const FilterFunc&) [with T = int; Filter<T>::FilterFunc = std::function<bool(const int&)>]’:
prog.cpp:19:17: internal compiler error: in tsubst_copy, at cp/pt.c:12141
Please submit a full bug report,
with …Run Code Online (Sandbox Code Playgroud) 在处理类成员函数指针时,我们可以使用以下语法在对象实例上调用函数:
struct X {
void foo();
};
X x; // Instance
auto f = &X::foo; // Member function pointer
(x.*f)(); // Call function f on x
Run Code Online (Sandbox Code Playgroud)
当有一个实例的原始指针时,语法是这样的:
X *xptr = new X();
(xptr->*f)();
Run Code Online (Sandbox Code Playgroud)
这很好地遵循了静态函数调用的类比:
x.foo();
x->foo();
Run Code Online (Sandbox Code Playgroud)
但是,当我有一个类的智能指针时,这不起作用:
unique_ptr<X> xsptr(new X());
(xsptr->*f)(); // g++: error: no match for 'operator->*' in 'xsptr ->* f'
Run Code Online (Sandbox Code Playgroud)
我通过首先应用取消引用运算符,然后使用以下.语法调用来解决此问题:
((*xsptr).*f)();
Run Code Online (Sandbox Code Playgroud)
这是有多丑?
编译器是否应该拒绝上面的箭头语法?因为通常(静态调用函数时),它调用operator ->. 不应该->*也只是打电话operator ->吗?
编译器错误部分地回答了这个问题:错误读作我们可以重载operator ->*以调用解除引用对象上的成员函数指针,但unique_ptr事实并非如此。但这带来了更多的问题。如果语言需要这样做,为什么智能指针不这样做?是不是打算不这样做,因为它引入了其他问题?为什么我们必须写这个操作符,而不是隐式调用返回的对象上的成员函数指针->?(因为这是写作时的行为xsptr->foo() …
c++ member-function-pointers smart-pointers operator-overloading c++11
最近,我需要声明一个字符串数组,所以我写下了以下语句:
const char** directories = {"cricket_batting", "cricket_bowling", "croquet", "tennis_forehand", "tennis_serve", "volleyball_smash"};
Run Code Online (Sandbox Code Playgroud)
但是,g ++向我显示了错误:
error: scalar object ‘directories’ requires one element in initializer
Run Code Online (Sandbox Code Playgroud)
所以我把声明改为:
const char* directories[] = {"cricket_batting", "cricket_bowling", "croquet", "tennis_forehand", "tennis_serve", "volleyball_smash"};
Run Code Online (Sandbox Code Playgroud)
这一次,这是对的.但我不能确切地知道之间的区别char**和char[].
我有一个字符串包含(未IS)JSON编码的数据,像在本例中:
foo([1, 2, 3], "some more stuff")
| |
start end (of JSON-encoded data)
Run Code Online (Sandbox Code Playgroud)
我们在应用程序中使用的完整语言嵌套了JSON编码的数据,而其他语言则是微不足道的(只是递归的东西).在递归解析器中从左到右解析这样的字符串时,我知道当我遇到JSON编码的值时,就像这里[1, 2, 3]从索引4开始.解析这个子字符串后,我需要知道结束位置以继续解析其余的的字符串.
我想将这个子字符串传递给QJsonDocumentQt5中经过良好测试的JSON解析器.但是在阅读文档时,不可能仅将子字符串解析为JSON,这意味着只要解析的数据结束(在使用]此处之后)控制返回而不报告解析错误.此外,我需要知道结束位置继续解析我自己的东西(这里剩下的字符串是, "some more stuff")).
为此,我曾经使用自定义JSON解析器,它通过引用获取当前位置并在完成解析后更新它.但由于它是业务应用程序的安全关键部分,我们不想再坚持使用我自己设计的解析器了.我的意思是QJsonDocument,所以为什么不使用它.(我们已经使用Qt5了.)
作为一种解决方法,我正在考虑这种方法:
QJsonDocument解析从当前位置开始的子字符串(这是无效的JSON)QJsonDocument再次解析,但这次子串具有正确的结束位置第二个想法是编写一个"JSON端扫描器",它接受整个字符串,一个起始位置并返回JSON编码数据的结束位置.这也需要解析,因为不匹配的括号/括号可以出现在字符串值中,但与完全手工制作的JSON解析器相比,编写(和使用)这样的类应该更容易(也更安全).
有没有人有更好的主意?