如果模板函数存在,如何调用模板函数? [英] How to call a templated function if it exists, and something else otherwise?

查看:149
本文介绍了如果模板函数存在,如何调用模板函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做类似

template <typename T>
void foo(const T& t) {
   IF bar(t) would compile
      bar(t);
   ELSE
      baz(t);
}



我想过使用 enable_if 会在这里做这项工作,将 foo 分成两部分,但我似乎无法解决细节。

I thought that something using enable_if would do the job here, splitting up foo into two pieces, but I can't seem to work out the details. What's the simplest way of achieving this?

推荐答案

有两种查找方式可以为 bar 。一个是在 foo 的定义上下文的无限制查找。另一种是在每个实例化上下文的参数依赖查找(但是在每个实例化上下文的查找结果不允许改变两个不同实例化上下文之间的行为)。

There are two lookups that are done for the name bar. One is the unqualified lookup at the definition context of foo. The other is argument dependent lookup at each instantiation context (but the result of the lookup at each instantiation context is not allowed to change behavior between two different instantiation contexts).

要获得所需的行为,您可以在 fallback 命名空间中定义一个备用函数,类型

To get the desired behavior, you could go and define a fallback function in a fallback namespace that returns some unique type

namespace fallback {
  // sizeof > 1
  struct flag { char c[2]; };
  flag bar(...);
}

bar 如果没有其他匹配,则将被调用,因为省略号具有最差的转换成本。现在,通过 fallback 的using指令将这些候选项包含到函数中,以使 fallback :: bar 候选人调用 bar

The bar function will be called if nothing else matches because the ellipsis has worst conversion cost. Now, include that candidates into your function by a using directive of fallback, so that fallback::bar is included as candidate into the call to bar.

现在,要查看是否调用 bar 解析为您的函数,您将调用它,并检查是否返回类型为 flag 。否则选择的函数的返回类型可能是void,所以你必须做一些逗号运算符技巧来解决。

Now, to see whether a call to bar resolves to your function, you will call it, and check whether the return type is flag. The return type of an otherwise chosen function could be void, so you have to do some comma operator tricks to get around that.

namespace fallback {
  int operator,(flag, flag);

  // map everything else to void
  template<typename T> 
  void operator,(flag, T const&);

  // sizeof 1
  char operator,(int, flag);
}

如果选择了我们的函数,那么逗号运算符调用将返回 int 。如果没有,或者如果选择的函数返回 void ,则调用依次返回 void 。然后,如果我们的回退被选择, flag 作为第二个参数的下一个调用将返回一个sizeof为1的类型,sizeof大于1(内置的逗号运算符将是因为 void 在混合中)如果选择了其他选项。

If our function was selected then the comma operator invocation will return a reference to int. If not or if the selected function returned void, then the invocation returns void in turn. Then the next invocation with flag as second argument will return a type that has sizeof 1 if our fallback was selected, and a sizeof greater 1 (the built-in comma operator will be used because void is in the mix) if something else was selected.

我们比较sizeof和委托给一个struct。

We compare the sizeof and delegate to a struct.

template<bool>
struct foo_impl;

/* bar available */
template<>
struct foo_impl<true> {
  template<typename T>
  static void foo(T const &t) {
    bar(t);
  }
};

/* bar not available */
template<>
struct foo_impl<false> {
  template<typename T>
  static void foo(T const&) {
    std::cout << "not available, calling baz...";
  }
};

template <typename T>
void foo(const T& t) {
   using namespace fallback;

   foo_impl<sizeof (fallback::flag(), bar(t), fallback::flag()) != 1>
     ::foo(t);
}

如果现有函数具有省略号,此解决方案是不明确的。但这似乎不太可能。使用后备测试进行测试:

This solution is ambiguous if the existing function has an ellipsis too. But that seems to be rather unlikely. Test using the fallback:

struct C { };
int main() {
  // => "not available, calling baz..."
  foo(C());
}

如果使用参数依赖查找找到候选项

And if a candidate is found using argument dependent lookup

struct C { };
void bar(C) {
  std::cout << "called!";
}
int main() {
  // => "called!"
  foo(C());
}

要在定义上下文中测试无限额查找,让我们定义上面的 foo_impl foo (将foo_impl模板置于 foo 具有相同的定义上下文)

To test unqualified lookup at definition context, let's define the following function above foo_impl and foo (put the foo_impl template above foo, so they have both the same definition context)

void bar(double d) {
  std::cout << "bar(double) called!";
}

// ... foo template ...

int main() {
  // => "bar(double) called!"
  foo(12);
}

这篇关于如果模板函数存在,如何调用模板函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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