扔烂番茄之前
我知道lambda分解的实际应用目前受到限制,因为无法找到替代失败友好的方法来检查隐藏在分解变量中的lambda捕获数量。这只是一个理论问题,因为我找不到涵盖捕获成员变量访问修饰符的任何标准部分。
例
int main() {
int a;
auto [x] = [a]{};
static_cast<void>(a);
static_cast<void>(x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
标准参考
关于lambda捕获的标准部分很长,因此我可能错过了相关的片段。我注意到的是,重点是对应于捕获的非静态成员必须/未命名。
这个问题的后续行动.假设占位符可用于推导构成非类型模板参数的函数指针的结果类型.c ++ 17是否允许在传递给模板函数名称时执行重载解析 - 不知道结果类型,执行隐式转换需要什么?
template <auto(*)(int)>
struct Foo { };
int bar(int);
float bar(float);
int main() {
static_cast<void>(Foo<bar>{});
}
Run Code Online (Sandbox Code Playgroud)
假设我们想要创建一个帮助类来反转模板包,例如如下:
#include <tuple>
#include <utility>
#include <typeinfo>
#include <iostream>
template <class>
struct sizer;
template <template<class...> class Pack, class... Args>
struct sizer<Pack<Args...>> {
static constexpr size_t value = sizeof...(Args);
};
template <class Pack, class Indices = std::make_index_sequence<sizer<Pack>::value>>
struct reverse_pack;
template <class... Args, size_t... I>
struct reverse_pack<std::tuple<Args...>, std::integer_sequence<std::size_t, I...>> {
using type = typename std::tuple<typename std::tuple_element<(sizeof...(Args) - I - 1), std::tuple<Args...>>::type...>;
};
int main() {
std::cout << typeid(reverse_pack<std::tuple<int, float, double>>::type).name() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我们可以使用例如函数签名作为模板参数成功完成相同的事情:
#include <utility>
#include <typeinfo>
#include <iostream>
template <class> …
Run Code Online (Sandbox Code Playgroud) 考虑一个简单的例子:
struct FooParent {
virtual void bar() { }
};
struct Foo: FooParent {
void bar() { }
};
int main() {
Foo foo;
void (Foo::*foo_member)() = &FooParent::bar;
//(foo.*FooParent::foo_member)();
foo.FooParent::bar();
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,foo
在调用 bar 成员函数时可以在对象上使用范围解析,但无法显式声明成员函数指针的范围。我同意在使用时应禁止该语法,->*
因为运算符有时可能会以意想不到的方式重载,但我无法理解在取消引用时阻止显式范围解析背后的原因.*
。
我正在尝试禁用指向基类的虚函数的成员指针的虚拟分派。
c++ virtual-functions member-pointers dereference language-lawyer
考虑一个简单的例子:
#include <type_traits>
template <class T, std::size_t N>
struct MaybeAssert {
using type = T;
static_assert(N < 1, "Assertion");
};
template <class T>
void foo(typename MaybeAssert<T, 0>::type) {
}
template <class T>
void foo(typename MaybeAssert<T, 0>::type,
typename MaybeAssert<T, 1>::type) {
}
int main() {
foo<int>(2);
}
Run Code Online (Sandbox Code Playgroud)
[gcc]实例化MaybeAssert<T, 1>
示例中的哪个触发器static_assert
.
另一方面,[clang]仅在函数模板参数的数量匹配时才实例化类型.哪个编译器是对的?
我知道这个问题相当理论化,但我认为如果将占位符定义为模板,例如:
namespace std {
namespace placeholders {
template <size_t> struct placeholder { constexpr placeholder() {}; };
template <size_t N> constexpr placeholder<N> _{};
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
std::bind(foo, std::placeholders::_<1>, std::placeholders::_<2>);
Run Code Online (Sandbox Code Playgroud)
或者对于c ++ 11:
namespace std {
namespace placeholders {
template <size_t> struct _ { };
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
std::bind(foo, std::placeholders::_<1>{}, std::placeholders::_<2>{});
Run Code Online (Sandbox Code Playgroud)
代码不会丢失任何清晰度,我们可以使用它做一些奇特的元编程.那么......为什么不std::bind
使用非类型模板参数实现占位符?
是否vector.erase
调整矢量对象,这样我可以用测量尺寸减小vector.size()
?
例如;
vector<int> v(5);
v = {1,2,3,4,5};
Run Code Online (Sandbox Code Playgroud)
我想删除4 by;
v.erase(v.begin()+4);
Run Code Online (Sandbox Code Playgroud)
我的矢量对象v
现在的大小是4 吗?换句话说就是v.size() == 4
经过这次手术?