想象一下,我有这个结构:
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标准。
答案 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