具有特殊功能的拉开功能类型
Posted
技术标签:
【中文标题】具有特殊功能的拉开功能类型【英文标题】:Pull Apart Function Type With Specialized Function 【发布时间】:2016-07-19 16:30:26 【问题描述】:this question 的答案使用类模板来挑选函数类型:
template <typename T>
struct function_args ;
template <typename R, typename... Args>
struct function_args<R(Args...)>
using type = tuple<Args...>;
;
template <typename T>
using decltypeargs = typename function_args<T>::type;
当我研究这里所做的事情时,我试图重写function_args
。我尝试使用一个函数来做到这一点,以消除对decltypeargs
模板的需要。但发现自己陷入了不正确的语法:
罢工>
template <typename T>
tuple<> myTry();
template <typename Ret, typename... Args>
tuple<Args...> myTry<Ret(Args...)>();
我希望调用decltype(myTry<decltype(foo)>())
来获得tuple
类型,而不必调用decltypeargs<decltype(foo)>
。有没有办法通过函数声明来做到这一点?
【问题讨论】:
你不能用函数模板做部分特化。但我想你想问点别的。我不太清楚。 @Arunmu 听起来你已经回答了我的问题。但我不确定如何改进措辞。我试图将函数的返回和参数分开,我需要使用专业化来做到这一点。我想用一个函数来做,但听起来我做不到。是不是更清楚了? 不确定您要做什么。myTry()
只是打字多于不使用 - 你要解决的问题是什么?
@JonathanMee 是的,更好,但恐怕答案还是一样的:)
@Barry 我只是想用对我更有意义的术语(函数声明)重写你的答案。但似乎函数声明不能像这样专门化。所以我只需要更适应专门化的对象。
【参考方案1】:
使用函数,您可以重用以前的相同类型特征:
template <typename T>
function_args<T> myTry();
或者您可以使用函数重新实现相同的功能。你不能部分特化函数模板,但你可以重载:
namespace detail
template <class T> struct tag ;
template <class R, class... Args>
tag<std::tuple<R, Args...>> myTry(tag<R(Args...)> );
template <class R, class C, class... Args>
tag<std::tuple<R, Args...>> myTry(tag<R(C::*)(Args...)> );
// etc.
template <typename T>
auto myTry() return detail::myTry(detail::tag<T>);
【讨论】:
tag
是干什么用的?
@Cheersandhth.-Alf 这就是他用来破解部分专业化的方法。从根本上说,这是我的坏问题,显然正确的答案就是使用结构,这只是一个创造性的解决方法。
myTry
的 2 个定义在没有 tag
的情况下将是不同的重载。
@Cheersandhth.-Alf 是的,但链接问题的兴趣在于提取参数类型。 tag
允许我们在函数参数的上下文中执行此操作。如果您能想到在函数中执行此操作的更好方法,我会说您已经提出了更好的解决方案,并且应该将其发布为答案。【参考方案2】:
//------------------------ Machinery:
#include <tuple>
template< class Ret, class... Args >
std::tuple<Args...> m( Ret(Args...) );
//------------------------- Example:
#include <iostream>
#include <typeinfo>
void foo( double );
using namespace std;
auto main()
-> int
using Args_tuple = decltype( m( foo ) );
cout << typeid( Args_tuple ).name() << endl;
【讨论】:
呃。这正是我无法将如何做的事情,就在一个功能中。当你第一次就能做对时,谁需要专业化? 我在这里问了一个后续问题:***.com/q/38482805/2642059 我想我一定不能很好地掌握decltype(m(foo))
的工作原理,因为我无法将其扩展为使用方法。
【参考方案3】:
函数不能像那样专门化,但您不需要为此专门化函数。使用 gcc 6.1.1 测试:
#include <iostream>
#include <tuple>
template <typename T> struct my_try;
template <typename Ret, typename... Args>
struct my_try<Ret(Args...)>
std::tuple<Args...> operator()();
;
template<typename T>
auto MyTry()
return my_try<T>()();
void foo(int, char);
int main()
decltype(MyTry<decltype(foo)>()) t;
int *a= &std::get<0>(t);
char *b= &std::get<1>(t);
return 0;
【讨论】:
哈哈,我想这确实是在一个函数中完成的。我希望 replace 用函数替换结构。 It sounds as though that's not possible though。也许你可以引用一些官方的说法来代替这个,指定函数不能被专门化? 我看不出替换结构有什么好处。编译后,它正好占用 0 位。 你完全正确。我只是觉得函数声明更舒服,所以我尝试使用它们。所以答案很简单:“你不能那样做。”但是,如果我们能在此处引用“因为我这么说”以外的其他内容,那就太好了。 @JonathanMee:函数可以完全特化,但不能部分特化。 很难为此提供标准的引用,因为它并没有真正说明函数模板不能部分特化的任何地方;它只是没有说它们 可以 (虽然它有 14.5.5 小节专门讨论类模板部分特化,但这与讨论显式模板特化的 14.7.3 小节和 14.8 节不同)。以上是关于具有特殊功能的拉开功能类型的主要内容,如果未能解决你的问题,请参考以下文章
24.编写一个Car类,具有String类型的属性品牌,具有功能drive; 定义其子类Aodi和Benchi,具有属性:价格型号;具有功能:变速; 定义主类E,在其main方法中分别创建Aodi和(