lambda的仅类型模板参数

时间:2016-10-09 19:52:35

标签: c++ templates lambda c++14

想象一下,我有这个结构:

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

当此结构转换为int时,它返回11,但是当转换为unsigned int时,它返回22.

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

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

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

直到现在,当我尝试使用lambdas时,一切都没问题:

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

现在,当调用lambda为lambda(0)时,它返回11,并将其称为lambda(0U),返回22

这可以正常工作,虽然相当“hacky”,但需要使用该类型的实例,这对于较大类型来说并不理想。 因此,实现这一目标的另一种方式,甚至是“hackier”:

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

现在将其称为lambda((int*)NULL)会返回11,但将其称为lambda((unsigned int*)NULL)会返回22。 您可能已经注意到这是相当冗长和“hacky”,所以我尝试了一种更直接和传统的方法:

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

起初我认为它不会编译,因为我没有在任何地方看到这种语法,但它确实编译(至少使用GCC)。但是,在尝试调用它时,错误会显示出来:

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<class T> main()::<lambda()>,但这不会编译:

lambda<int>() - &gt; error: expected primary-expression before ‘int’

所以,我的问题是:如果有的话,官方的,符合标准的方式是什么?我真的希望指针黑客不是唯一的方法。在真实代码中使用它似乎非常笨拙。

我正在使用G ++(GCC 5.4.0)作为我的编译器。我也使用像-std=c++14这样的C ++ 14标准。

1 个答案:

答案 0 :(得分:7)

您可以传递空标记类型的变量模板:

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

你可以写下你的lambda:

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