c – 尾随返回类型和标记分派

c – 尾随返回类型和标记分派,第1张

概述尝试使用尾随返回类型和标记调度,我编写了以下代码. #include <string>#include <iostream>using namespace std;namespace Params{struct t_param1{};struct t_param2{};};template<typename t_detail>struct Select;template 尝试使用尾随返回类型和标记调度,我编写了以下代码.

#include <string>#include <iostream>using namespace std;namespace Params{struct t_param1{};struct t_param2{};};template<typename t_detail>struct Select;template<>struct Select<Params::t_param1> {using choice = Params::t_param1;};template<>struct Select<Params::t_param2> {using choice = Params::t_param2;};class Tester{private:    using t_uint32 = uint32_t;    using t_string = string;private:    t_uint32 m_param1;//      t_string m_param2;private:    template<typename t_entity>    voID assign(const Params::t_param1&,t_entity&& entity);    template<typename t_entity>    voID assign(const Params::t_param2&,t_entity&& entity);    auto access(const Params::t_param1&) -> decltype(m_param1);//      auto access(const Params::t_param2&) -> decltype(m_param2);public:    template<typename t_detail,typename t_entity>    voID assign(t_entity&& entity);    template<typename t_detail>    auto access() -> decltype(access(typename Select<t_detail>::choice()));};template<typename t_detail,typename t_entity>voIDTester::assign(t_entity&& entity){assign(typename Select<t_detail>::choice(),entity);}template<typename t_entity>voIDTester::assign(const Params::t_param1&,t_entity&& entity){m_param1 = entity;cout << "Assigned m_param1 with " << entity << endl;}/*template<typename t_entity>voIDTester::assign(const Params::t_param2&,t_entity&& entity){m_param2 = entity;cout << "Assigned m_param2 with " << entity << endl;}*/template<typename t_detail>autoTester::access()-> decltype(access(typename Select<t_detail>::choice())){return(access(typename Select<t_detail>::choice()));}autoTester::access(const Params::t_param1&)-> decltype(m_param1){return(m_param1);}/*autoTester::access(const Params::t_param2&)-> decltype(m_param2){return(m_param2);}*/int main() {auto tester = Tester();tester.assign<Params::t_param1>(79);//  tester.assign<Params::t_param2>("viziv");auto param1 = tester.access<Params::t_param1>();//  auto param2 = tester.access<Params::t_param2>();cout << "Access: param1 = " << param1 << endl;//  cout << "Access: param2 = " << param2 << endl;return 0;}

当我使用Apple LLVM版本7.0.2(clang-700.1.81)编译此代码时,我得到以下编译错误

junk1.cpp:78:9: error: out-of-line deFinition of 'access' does not match any declaration in 'Tester'Tester::access()        ^~~~~~1 error generated.

奇怪的是,当我取消注释代码以分配和访问param2(在上面的代码中注释掉)时,它编译得很好并产生所需的结果.

我究竟做错了什么?任何人都可以向我解释为什么包含param2会改变编译行为吗?

解决方法 我认为这里有一个半问题.

第一个原因是使用尾随返回类型实质上创建了模板化函数.当您尝试使用类的函数时,类类型不能是不完整的.

这就是为什么将公共访问方法的函数定义移动到类声明中的原因(Demo);只要尚未定义公共访问方法,该类就不完整,并且在该类完成之前无法定义该方法.

注意,解决此问题的另一种方法是,如果私有版本的访问以某种方式是非成员函数(例如,周围范围中的自由浮动函数).

这种方法的问题(问题的一半,因为你实际上并没有尝试这样做)是,尝试调用现在免费的浮动版访问需要编译器评估所有可能的重载,包括公共模板化访问(感谢ADL).当发生这种情况时,在non-deduced context中评估Select< t_detail> :: choice,并且无法获得实际的基础类型.

因此,如果我们都将Tester之外的私有访问权移动并重命名为(类似于access2),那么我们可以将声明与公共访问功能的定义分开(Demo)

总结

以上是内存溢出为你收集整理的c – 尾随返回类型和标记分派全部内容,希望文章能够帮你解决c – 尾随返回类型和标记分派所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1224674.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存