{"id":4413,"date":"2013-05-09T07:00:00","date_gmt":"2013-05-09T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/05\/09\/why-am-i-getting-lnk2019-unresolved-external-for-my-inline-function\/"},"modified":"2013-05-09T07:00:00","modified_gmt":"2013-05-09T07:00:00","slug":"why-am-i-getting-lnk2019-unresolved-external-for-my-inline-function","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20130509-00\/?p=4413\/","title":{"rendered":"Why am I getting LNK2019 unresolved external for my inline function?"},"content":{"rendered":"<p><P>\nMore than once, I&#8217;ve seen somebody confused by how inline functions work.\n<\/P>\n<BLOCKQUOTE CLASS=\"m\">\n<P>\nI have implemented a few inline functions in one of my cpp files,\nand I want to use it from other cpp files,\nso I declare them as <CODE>extern<\/CODE>.\nBut sometimes I will get linker error 2019 (unresolved external)\nfor the inline functions.\n<\/P>\n<PRE>\n\/\/ a.cpp\ninline bool foo() { return false; }<\/p>\n<p>\/\/ b.cpp\nextern bool foo();<\/p>\n<p>bool bar() { return foo(); }\n<\/PRE>\n<\/BLOCKQUOTE>\n<P>\nYup, that&#8217;s right.\nThe C++ language says in section 3.2(3) [C++03, C++11],\nand repeats in section 7.1.2(4) [C++03, C++11],\n<\/P>\n<BLOCKQUOTE CLASS=\"q\">\nAn inline function shall be defined\nin every translation unit in which it is used.\n<\/BLOCKQUOTE>\n<P>\n(A <I>translation unit<\/I> is the technical term for what\nwe intuitively can think of as a single cpp file and all the\nfiles that it <CODE>#include<\/CODE>s.)\n<\/P>\n<P>\nBy putting the definition of <CODE>foo<\/CODE> in a cpp file,\nyou make its definition visible only to that cpp file and\nno other cpp file.\nWhen you compile <CODE>b.cpp<\/CODE>,\nsees that you declared it as a normal external function,\nso it generates a call to it like a normal external function.\nOn the other hand, when you compile <CODE>a.cpp<\/CODE>,\nthe compiler sees that <CODE>foo<\/CODE> is an inline function,\nso it says,\n&#8220;I don&#8217;t need to generate any code yet.\nInline functions generate code at the point they are invoked,\nnot at the point they are defined.&#8221;\n<\/P>\n<P>\nResult:\n<CODE>b.cpp<\/CODE> asks for a definition of <CODE>foo<\/CODE>,\nbut nobody provides it,\nbecause the two declarations were inconsistent.\nThis is a violation of\n7.1.2(4) [C++03, C++11]\nwhich says\n&#8220;If a function with external linkage is\ndeclared inline in one translation unit,\nit shall be declared inline in all translation units in which it appears;\nno diagnostic is required.&#8221;\nThe magic phrase <I>no diagnostic is required<\/I> means that the compiler\nis not even required to report the error.\n(You&#8217;re lucky that it did!)\n<\/P>\n<P>\nThis rule makes sense when you think about the classical model of\ncompiling:\nThe compiler logically\ntakes the source code and sends it through the\npreprocessor.\nThe result (the <I>translation unit<\/I>)\nthen goes into the compiler proper,\nwhich learns about structures and classes and functions,\nand it generates code based on what it sees in that\ntranslation unit.\nThe compiler does not have access to other translation units,\nso when compiling <CODE>a.cpp<\/CODE> it can&#8217;t peek into\n<CODE>b.cpp<\/CODE> and say,\n&#8220;Hm, it looks like somebody is going to be calling <CODE>foo<\/CODE>\nas a non-inline function,\nso let me also generate a non-inline version of it.&#8221;\nAnd similarly,\nwhen the compiler is generating code for the\n<CODE>bar<\/CODE> function,\nit doesn&#8217;t peek into <CODE>a.cpp<\/CODE> and say,\n&#8220;Hm, it looks like <CODE>foo<\/CODE> is actually an inline\nfunction.\nLet me go steal its definition from that other file.&#8221;\n<\/P>\n<P>\nThe solution is to\n<A HREF=\"http:\/\/www.parashift.com\/c++-faq-lite\/inline-functions.html#faq-9.6\">\nmove the definition of the inline function into the header file<\/A>.\n<\/P>\n<P>\nNow you can solve this problem:\n<\/P>\n<BLOCKQUOTE CLASS=\"m\">\n<P>\nI&#8217;m getting error LNK2019 for my <CODE>Get&shy;Value<\/CODE> method.\nCan somebody explain why?\n<\/P>\n<PRE>\n\/\/ Widget.h\nclass Widget\n{\npublic:\n Widget(int initialValue) : value_(initialValue) { }\n void SetValue(int value);\n inline int GetValue();\nprivate:\n int value_;\n};<\/p>\n<p>\/\/ Widget.cpp\n#include &lt;widget.h&gt;<\/p>\n<p>inline int Widget::GetValue()\n{\n return value_;\n}<\/p>\n<p>\/\/ Other.cpp<\/p>\n<p>void something()\n{\n Widget widget(42);\n printf(&#8220;%d&#8221;, widget.GetValue());\n}\n<\/PRE>\n<\/BLOCKQUOTE><\/p>\n","protected":false},"excerpt":{"rendered":"<p>More than once, I&#8217;ve seen somebody confused by how inline functions work. I have implemented a few inline functions in one of my cpp files, and I want to use it from other cpp files, so I declare them as extern. But sometimes I will get linker error 2019 (unresolved external) for the inline functions. [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-4413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>More than once, I&#8217;ve seen somebody confused by how inline functions work. I have implemented a few inline functions in one of my cpp files, and I want to use it from other cpp files, so I declare them as extern. But sometimes I will get linker error 2019 (unresolved external) for the inline functions. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/4413","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=4413"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/4413\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=4413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=4413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=4413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}