我发现在下面有一个简洁的语法并不简单:
std::function<int(float, bool)>
Run Code Online (Sandbox Code Playgroud)
如果我将该函数声明为:
template <class RetType, class... Args>
class function {};
Run Code Online (Sandbox Code Playgroud)
定义函数的模板类型是一种普通的语法:
function<int,float,bool> f;
Run Code Online (Sandbox Code Playgroud)
但它适用于部分模板专业化的奇怪技巧
template <class> class function; // #1
template <class RV, class... Args>
class function<RV(Args...)> {} // #2
Run Code Online (Sandbox Code Playgroud)
这是为什么?为什么我需要为模板提供一个空类型参数(#1),否则它将无法编译
说我有以下功能
void doWork(Widget && param) // param is an LVALUE of RRef type
{
Widget store = std::move(param);
}
Run Code Online (Sandbox Code Playgroud)
为什么我需要param回到rvalue std::move()?是不是很明显,paramrvalue 的类型是因为它在函数签名中被声明为右值引用?不应该仅仅根据这个原则自动调用移动构造函数吗?
为什么不默认发生这种情况?
c++ rvalue-reference move-constructor lvalue-to-rvalue stdmove
我研究了泛型lambdas,稍微修改了这个例子,所以我的lambda应该捕获上层lambda的可变参数包.所以基本上给予上层lambda的是(auto&&...)- 应该以某种方式在[=]块中捕获.
(完美的转发是另一个问题,我很好奇这可能在这里吗?)
#include <iostream>
#include<type_traits>
#include<utility>
// base case
void doPrint(std::ostream& out) {}
template <typename T, typename... Args>
void doPrint(std::ostream& out, T && t, Args && ... args)
{
out << t << " "; // add comma here, see below
doPrint(out, std::forward<Args&&>(args)...);
}
int main()
{
// generic lambda, operator() is a template with one parameter
auto vglambda = [](auto printer) {
return [=](auto&&... ts) // generic lambda, ts is a parameter pack
{ …Run Code Online (Sandbox Code Playgroud) 我使用静态struct member技巧来强制执行第二次传递编译,但仍然出现错误:
struct S
{
template <typename T>
static T Sum(T t) {
return t;
}
template <typename T, typename ... Rest>
static auto Sum(T t, Rest... rest) -> decltype(t + Sum(rest...) )
{
return t + Sum(rest...);
}
};
int main()
{
auto x = S::Sum(1,2,3,4,5);
}
Run Code Online (Sandbox Code Playgroud)
main.cpp:17:14:调用'Sum'没有匹配函数
我使用模板化引用来通过引用函数类型捕获函数但是当我尝试通过param()调用它时崩溃(使用Apple LLVM版本9.0.0(clang-900.0.38),x86_64-apple-darwin17 3.2.0)
#include <iostream>
#include <typeinfo>
int doit(int a, int b) {
return a+b;
}
template <typename T>
void test(T & param) {
std::cout << typeid(T).name() << " ";
std::cout << typeid(param).name() << " ";
std::cout << param(3,5);
}
int main()
{
test(doit);
}
Run Code Online (Sandbox Code Playgroud)
但根据Scott Meyers的书"函数类型可以衰减到函数指针":
void someFunc(int, double); // someFunc is a function; type is void(int, double)
template<typename T>
void f1(T param); // in f1, param passed by value
template<typename T>
void f2(T& param); // in f2, param …Run Code Online (Sandbox Code Playgroud) 也许是它的蹩脚问题,但我不明白!如果我包含<string>或<vector>在多个翻译单元(不同的.cpp)中为什么它不会破坏ODR?据我所知,每个.cpp的编译方式都不同,因此将分别为每个目标文件生成vector的方法代码,对吧?所以链接器应该检测它并抱怨.即使它不会(我怀疑它是模板的特殊情况)它将在每个单元中使用一个代码或不同的克隆代码集,当我将所有链接在一起时???
我想创建一个模板类或函数,它接收 lambda,并将其内部放入 std::function<> Lambda 可以有任意数量的输入参数 [](int a, float b, ...) std:: function<> 应该对应于 lambda 的 operator() 的类型
template <typename T>
void getLambda(T t) {
// typedef lambda_traits::ret_type RetType; ??
// typedef lambda_traits::param_tuple --> somehow back to parameter pack Args...
std::function<RetType(Args...)> fun(t);
}
int main() {
int x = 0;
getLambda([&x](int a, float b, Person c){});
}
Run Code Online (Sandbox Code Playgroud)
所以我需要以某种方式提取返回类型和参数包
这里的答案建议在 lambda 的 :: operator() 上使用部分规范
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args> …Run Code Online (Sandbox Code Playgroud) 基本上我想要做的是创建一个函数模板,它接受任何Callable(函数类型/ lambda/Functor)并返回一个lambda-taking-the-similar-args-list并返回原始类型的返回类型
#include <iostream>
int func(int a,float b) {
return a+b;
}
struct callable {
int operator() (int a, float b) {
return a+b;
}
};
template <typename RV, typename... Args>
auto getLambdaFromCallable(RV(&func)(Args...)) {
auto l = [&](Args... args) -> RV {
return func(args...);
};
return l;
}
int main() {
auto f = getLambdaFromCallable(func);
std::cout << f(1,2.f);
std::cout << " " << typeid(f).name();
auto f2 = getLambdaFromCallable(callable{}); // doesn't work
callable{}(1,2); // works
auto lambdaTest = [](int a, float …Run Code Online (Sandbox Code Playgroud) c++ templates functional-programming variadic-functions variadic-templates
我知道如何创建一个全局函数,使用可变参数模板将参数转发给类ctor(类似于shared_ptr模板类的make_shared <>):
template<typename T, typename... Args>
T Create (Args&&... args)
{
return T(args...); // RVO takes place here
}
Run Code Online (Sandbox Code Playgroud)
是否可以使用类似的方法为类中的静态工厂方法创建模板?我想使用类似的可变参数模板语法将所有参数组合转发给所有可能的构造函数(我不想重载或显式地将所有可能的ctors链接到静态方法,只是使用模板和编译器来完成这项工作),即在伪代码中( !)
class Class {
public:
static Class create(Args&&... args)
{
Class(args...);
}
Class(int) {} // ctor 1
Class(int, float) {} // ctor 2
//... etc
Run Code Online (Sandbox Code Playgroud)
有类似的参数转发
如果我直接使用variadic模板,它看起来像这样
template <typename... Args>
class Class {
public:
static Class create(Args&&... args)
{
return Class(args...);
}
Class(int) {} // ctor 1
Class(int, float) {} // ctor 2
};
Run Code Online (Sandbox Code Playgroud)
但它提供了丑陋的使用语法,我需要明确地为模板提供类型...
int main()
{
Class<int,float> a …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用嵌套的lambda捕获构造完美的转发(零复制)构造.我希望应该有零复制结构,但有些东西被打破了.
我从variadic arg移动.打包到元组(移动确定)然后我将元组(移动确定)传递给std :: apply并在最终嵌套的lambda中我组装另一个元组(预计移动正常但是Wrapper CTOR是COPY而不是移动:
#include <iostream>
// tuple printer (ignore it)
template<typename Type, unsigned N, unsigned Last>
struct tuple_printer {
static void print(std::ostream& out, const Type& value) {
out << std::get<N>(value) << ", ";
tuple_printer<Type, N + 1, Last>::print(out, value);
}
};
template<typename Type, unsigned N>
struct tuple_printer<Type, N, N> {
static void print(std::ostream& out, const Type& value) {
out << std::get<N>(value);
}
};
template<typename... Types>
std::ostream& operator<<(std::ostream& out, const std::tuple<Types...>& value) {
out << "(";
tuple_printer<std::tuple<Types...>, 0, …Run Code Online (Sandbox Code Playgroud) 找到这个代码示例
void *handle;
double (*cosine)(double);
handle = dlopen("libm.so", RTLD_LAZY);
*(void **) (&cosine) = dlsym(handle, "cos");
Run Code Online (Sandbox Code Playgroud)
我使用从右到左阅读规则来解析变量的类型:
double (*cosine)(double);
Run Code Online (Sandbox Code Playgroud)
在这里我从左到右书写但移动LTR:"余弦" - >"*" - >"是指针"然后"("我们走到最里面()范围 - >"(双)" - >"到函数取一个双" - >并返回最左边"双"
但这到底是什么意思?我甚至不知道从哪里开始解析)是"&cosine"的地址或参考?(void**)是什么意思?为什么它最左边的"*"?是取消引用还是类型?
*(void **) (&cosine)
Run Code Online (Sandbox Code Playgroud) 在Josuttis的书中,我有以下示例:
template<typename T1, typename T2>
auto max (T1 a, T2 b) -> decltype(b<a?a:b)
{
return b<a?a:b;
}
Run Code Online (Sandbox Code Playgroud)
但是
b<a
Run Code Online (Sandbox Code Playgroud)
部分属于运行时,对不对?那么,为什么要在decltype中对其进行比较(以在模板实例化期间找出静态类型)?以及它如何在编译时正常工作?
我想构建一个functon模板,它接受任何函数指针及其参数列表 - 并返回一个(有状态的)lambda,它将那些参数值绑定在里面(想想std :: bind但是基于lambda)
#include <iostream>
#include <vector>
template <class ...D>
class DEB;
template <class Ret, class ... Args>
auto getLambdaFromFunction(Ret(*func)(Args...)) {
return [func](Args ... ar){ // auto could work here but lambda is anyway templated by external template's Args
func(ar...);
};
}
template <class Ret, class ... Args>
auto wrapFunction(Ret(*func)(Args...),Args... args) {
return [=](){
func(args...);
};
}
int doone(int a, float b) {
std::cout << "do one";
return a;
}
int main() {
auto lw = …Run Code Online (Sandbox Code Playgroud)