【问题标题】:typedef works, 'using =' doesn'ttypedef 有效,'using =' 无效
【发布时间】:2014-07-14 05:45:33
【问题描述】:

我有一段代码,稍微简化一下,相当于以下代码,可以正确编译和工作。

template <typename Interface, typename... Args>
struct factory_function {
  typedef function<shared_ptr<Interface> (Args...)> type;
};

template <typename Interface, typename Implementer, typename... Args>
shared_ptr<Interface> create_function(Args... args) {
  return make_shared<Implementer>(args...);
}

template <typename Interface, typename... Args>
  int register_factory(identifier id, typename factory_function<Interface, Args...>::type factory) {
}

int main(int argc, char *argv[]) {
  register_factory<Iface>(1000, create_function<Iface, Impl>);
  return 0;
}

但是当尝试使用较新的 using ... = 构造而不是像这样的结构中的 typedef 时:

template <typename Interface, typename... Args>
using factory_function = function<shared_ptr<Interface> (Args...)>;

然后把typename factory_function&lt;Interface, Args...&gt;::type改成factory_function&lt;Interface, Args...&gt;,出现编译错误:

foo.cc: In function ‘int main(int, char**)’:
foo.cc:31:61: error: no matching function for call to ‘register_factory(int, <unresolved overloaded function type>)’
   register_factory<Iface>(1000, create_function<Iface, Impl>);
                                                         ^
foo.cc:31:61: note: candidate is:
foo.cc:17:5: note: template<class Interface, class ... Args> int register_factory(identifier, factory_function<Interface, Args ...>)
 int register_factory(identifier id, factory_function<Interface, Args...> factory) {
     ^
foo.cc:17:5: note:   template argument deduction/substitution failed:
foo.cc:31:61: note:   mismatched types ‘std::function<std::shared_ptr<Iface>(Args ...)>’ and ‘std::shared_ptr<Iface> (*)()’
   register_factory<Iface>(1000, create_function<Iface, Impl>);
                                                         ^
foo.cc:31:61: note:   could not resolve address from overloaded function ‘create_function<Iface, Impl>’

更新: 这是完整的、可编译的测试用例,使用g++ -std=c++11 foo.cc 编译:

#include <functional>
#include <memory>

using namespace std;

typedef int identifier;

template <typename Interface, typename... Args>
struct factory_function {
  typedef function<shared_ptr<Interface> (Args...)> type;
};
//template <typename Interface, typename... Args>
//using factory_function = function<shared_ptr<Interface> (Args...)>;

template <typename Interface, typename Implementer, typename... Args>
shared_ptr<Interface> create_function(Args... args) {
  return make_shared<Implementer>(args...);
}

template <typename Interface, typename... Args>
int register_factory(identifier id, typename factory_function<Interface, Args...>::type factory) {
//int register_factory(identifier id, factory_function<Interface, Args...> factory) {
}

class Iface {
public:
  virtual void foo() = 0;
};

class Impl : public Iface {
public:
  virtual void foo() {}
};

int main(int argc, char *argv[]) {
  register_factory<Iface>(1000, create_function<Iface, Impl>);
  return 0;
}

注释行显示了工作的内容。

【问题讨论】:

  • 请提供一个可编译的测试用例(不要跳过包含、类型定义等)。
  • 完成。查看新的更新。

标签: c++ templates c++11 typedef using


【解决方案1】:

使用int register_factory(identifier id, typename factory_function&lt;Interface, Args...&gt;::type factory),编译器无法推断出类型InterfaceArgs,因此对register_factory&lt;Iface&gt;(1000, create_function&lt;Iface, Impl&gt;);的调用显式为int register_factory(identifier id, typename factory_function&lt;Interface&gt;::type);

使用替代定义(使用)int register_factory(identifier id, factory_function&lt;Interface, Args...&gt;,编译器必须尝试推断 ArgsInterface 显式设置为 Iface)但不幸的是,需要转换并且编译器失败(std::shared_ptr&lt;Iface&gt; (*)()不完全匹配任何function&lt;std::shared_ptr&lt;Iface&gt;(Args...)&gt;)

解决方法是您的第二个解决方案是将create_function&lt;Iface, Impl&gt; 的类型强制为std::function。以下可能会有所帮助:

template <typename R, typename...Args>
std::function<R(Args...)> make_function(R (*f)(Args...))
{
    return f;
}

后来:

register_factory<Iface>(1000, make_function(create_function<Iface, Impl>));

【讨论】:

  • 我不确定我是否完全理解这一点。当我调用register_factory&lt;Iface&gt;(...) 时,我将Interface 显式设置为Iface 并将Args 设置为一个空列表。编译器需要推断什么?
  • 不,当您调用make_shared&lt;Implementer&gt;(args...) 时,您修复了Implementer,但仍会扣除args
  • create_function&lt;Iface, Impl&gt;: 这里Args 是固定的,不应推导出来。
  • 所以,如果我错了,请纠正我,当我们有 typename factory_function&lt;Interface, Args...&gt;::type 时,编译器必须将 std::shared_ptr&lt;Iface&gt; (*)()function&lt;std::shared_ptr&lt;Iface&gt;(Args...)&gt; 匹配,这是通过强制转换完成的,因为 ...::type 是一种类型.但是使用“using ... =”,factory_function&lt;Interface, Args...&gt;是一个模板,需要先匹配,然后再确定类型。所以编译器无法进行推演并失败。我说的对吗?
  • @Constructor: create_function&lt;Iface, Impl&gt; 是固定的,但它是一个指向函数的指针,而不是直接的std::function,哪个std::function 是正确的? (编译器必须检查无数种可能性)。
【解决方案2】:

您可以通过结合这两种方法使其工作;)

template <typename Interface, typename... Args>
struct fa_fu_helper {
  typedef function<shared_ptr<Interface> (Args...)> type;
};

template <typename Interface, typename... Args>
using factory_function = typename fa_fu_helper<Interface, Args...>::type;

【讨论】:

  • 这就是我最终解决问题的方法,尽管 Jarod42 的回答和 cmets 让我明白了问题的根源。
  • 只是为了确保,您可以fa_fu_helper 结构中执行using type = function&lt;/ *bla */&gt;;
  • 那你还是得像 fa_fu_helper 一样使用它<..>::type,不是吗?
猜你喜欢
  • 2023-03-05
  • 1970-01-01
  • 2012-01-25
  • 2023-03-04
  • 2011-12-01
  • 2012-10-20
  • 2011-04-05
  • 1970-01-01
  • 2019-04-15
相关资源
最近更新 更多