2014-10-03 42 views
2

假设用户定义的下列功能的一些子集:选择最优惠功能通过标签继承

void f(int) {} 
void g(int) {} 
void h(int) {} 
// ... 

你的任务是编写一个函数call_best(int)这就要求从声明的上面列表中的第一个函数(你然后可以假定它也被定义)。你是怎样做的?

+4

只是好奇,有什么用例呢? – 2014-10-03 09:36:52

+0

所有这些功能都已定义。 – 2014-10-03 09:55:50

+0

@NicolasHolthaus:我认为OP想要做一些类似于[调用免费函数而不是方法的方法](http://stackoverflow.com/questions/21441803/)调用一个免费函数而不是方法 - 如果它不存在) – Jarod42 2014-10-03 10:01:15

回答

4

首先,我们定义一个优先级。

template<unsigned P> struct priority : priority<P-1> {}; 
template<> struct priority<0> {}; 

它可以用来给一个总订单上的功能如下:

template<class Int> auto call_best(Int i, priority<2>) -> decltype(f(i)) { return f(i); } 
template<class Int> auto call_best(Int i, priority<1>) -> decltype(g(i)) { return g(i); } 
template<class Int> auto call_best(Int i, priority<0>) -> decltype(h(i)) { return h(i); } 

void call_best(int i) { call_best(i, priority<2>{}); } 

Int模板参数和decltype()确保只有定义函数争夺被称为(关键字SFINAE )。 priority标签类允许我们选择其中最好的一个。

请注意,SFINAE部件仅适用于您有至少有一个参数您可以模板。如果有人有关于如何避免这种情况的想法,请告诉我。

+0

只需声明其中一个函数就足够了。然后它会编译但不会链接。我也有兴趣对这有什么用处。 – jrok 2014-10-03 09:37:41

+0

据我所知,编译和运行,如果你至少定义了一个函数,请看这里:http://ideone.com/Jk4Dbo 当然,如果你没有定义任何函数,它就不会编译,但这是有意的行为。在这种情况下,人们最多可以将错误信息应用于某种表达方式。 – gTcV 2014-10-03 10:05:37

+0

如果'f','g'或'h'超负荷,这不会失败吗? – 2014-10-03 10:09:57

0

如果您遵循给出函数推导返回类型的惯例(即auto/decltype(auto)),则您的代码将起作用。这只能在C++ 14中完成,其中具有推导的返回类型的函数在定义之前不能使用(即使在未评估的操作数中),否则导致替换失败。这是你的例子,在铛3.5工作,但不幸的是不在g ++ 4.9。

template<unsigned P> struct priority : priority<P-1> {}; 
template<> struct priority<0> {}; 

// ******** 
auto f(int); 
auto g(int); 
auto h(int) { std::cout << "h()"; } 
// ******** 

template<class Int> auto call_best(Int i, priority<2>) -> decltype(f(i)) { return f(i); } 
template<class Int> auto call_best(Int i, priority<1>) -> decltype(g(i)) { return g(i); } 
template<class Int> auto call_best(Int i, priority<0>) -> decltype(h(i)) { return h(i); } 

void call_best(int i) { call_best(i, priority<2>{}); } 

int main() 
{ 
    call_best(0); // calls h() 
} 

clang 3.5 g++ 4.9