lambda的仅类型模板参数 [英] Type-only template argument to lambda

查看:171
本文介绍了lambda的仅类型模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下我有这个结构:

Imagine I've got this struct:

struct Foo {
    operator int() {
        return 11;
    }
    operator unsigned int() {
        return 22;
    }
} foo;

当这个struct转换为int时,它返回11,但是当转换为unsigned int时,它返回22。

When this struct is casted to an int, it returns 11, but when casted to an unsigned int, it returns 22.

使用普通函数,我可以使用模板和getter函数来选择:

Using normal functions, I could use templates and a getter function to choose:

template<typename T>
T get() {
    return (T)foo;
}

现在,调用此函数 get< int> ;()它会返回 11 ,但是当调用它 get< unsigned int>()它会返回 22

Now, when calling this function like get<int>() it would return 11, but when calling it like get<unsigned int>() it would return 22.

当我尝试使用lambdas时, / p>

Everything's alright until now, when I try to use lambdas instead:

auto lambda=[](auto type) {
    return (decltype(type))foo;
};

现在当调用lambda作为 lambda(0)它返回 11 ,并调用 lambda(0U)返回 22

Now when calling lambda as lambda(0) it returns 11, and calling it as lambda(0U) returns 22.

这可以正常工作,虽然相当hacky,但是类型的实例需要使用, 。
另一种方式弹出,甚至hackier,实现这一点:

This works correctly, although rather 'hacky', but an instance of the type needs to be used, which wouldn't be ideal with larger types. So another way springs up, even 'hackier', to achieve this:

auto lambda=[](auto* typePointer) {
    return (decltype(*typePointer))foo;
};

现在调用 lambda((int *)NULL)返回 11 ,但调用 lambda((unsigned int *)NULL)返回 22 。你可能已经注意到这是相当冗长和'hacky',所以我尝试一个更直接和传统的方法:

Now calling it as lambda((int*)NULL) returns 11 but calling it as lambda((unsigned int*)NULL) returns 22. As you might have noticed this is rather verbose and 'hacky', so I tried a more straightforward and traditional method:

auto lambda=[]<typename T>() {
    return (T)foo;
};

一开始我以为它不会编译,因为我没有在任何地方看到这个语法,它编译(至少使用GCC)。但是,当尝试调用它时,错误显示:

At first I thought it wouldn't compile, since I haven't seen this syntax anywhere, but it does compile (at least with GCC). However, when trying to call it, errors show up:

lambda();


testlambda.cpp: In function ‘int main()’:
testlambda.cpp:25:9: error: no match for call to ‘(main()::<lambda()>) ()’
  lambda();
         ^
testlambda.cpp:22:29: note: candidate: template<class T> main()::<lambda()>
  auto lambda=[]<typename T>() {
                             ^
testlambda.cpp:22:29: note:   template argument deduction/substitution failed:
testlambda.cpp:25:9: note:   couldn't deduce template parameter ‘T’
  lambda();
         ^

正如你所看到的,候选人是 template<类T> main()::< lambda()> ,但这不会编译:

As you can see, a candidate is template<class T> main()::<lambda()>, but this doesn't compile either:

; int>() - > 错误:'int'之前的预期主表达式

所以,我的问题是:什么是官方的,标准兼容的方式做这个,如果有?我真的希望指针hack不是唯一的方法。

So, my question is: What is the official, standard-compliant way of doing this, if any? I really hope the pointer hack isn't the only way. It seems really clumsy to use in real code.

我使用G ++(GCC 5.4.0)作为我的编译器。我也使用C ++ 14标准,如 -std = c ++ 14

推荐答案

您可以传递一个空标签类型的变量模板:

You can pass a variable template of an empty tag type:

template <class T> struct tag_t { using type = T; };
template <class T>
constexpr tag_t<T> tag{};

您可以像下面这样编写lambda:

You can write your lambda like:

auto lambda = [](auto type) {
    return static_cast<typename decltype(type)::type>(foo);
};

auto lambda = [](auto type) -> typename decltype(type)::type {
    return foo;
};

并调用它:

lambda(tag<int> ); // 11
lambda(tag<unsigned> ); // 22

这篇关于lambda的仅类型模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆