Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does inlining my accessors break my code?

I am experiencing a strange issue where attempting to inline the accessors for my "Person" class causes the code to fail to compile.

The following code will compile and run successfully (Using Visual Studio 2012):

Person.h

#pragma once
#include <string>

using namespace std;

class Person
{
public:
    Person(string name, int age = 0);
    ~Person(void);

    // Accessors
    string name(void) const;
    int    age (void) const;

private:
    string m_name;
    int    m_age;
};

Person.cpp

#include "stdafx.h"
#include "Person.h"


Person::Person(string name, int age) :
    m_name(name),
    m_age (age )
{}


Person::~Person(void) {}

string Person::name(void) const
{
    return m_name;
}

int Person::age(void) const
{
    return m_age;
}

header_test.cpp

#include "stdafx.h"
#include <iostream>
#include "Person.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    Person p("Joe");

    cout << p.name() << endl;

    return 0;
}

If I change my accessors to be defined as inline functions the code breaks.

Inlining the accessors in Person.h

// Accessors
inline string name(void) const;
inline int    age (void) const;

Inlining the accessors in Person.cpp

inline string Person::name(void) const
{
    return m_name;
}

inline int Person::age(void) const
{
    return m_age;
}

Doing this produces the following errors:

1>header_test.obj : error LNK2019: unresolved external symbol "public: class std::basic_string,class std::allocator > __thiscall Person::name(void)const " (?name@Person@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) referenced in function _wmain

1>fatal error LNK1120: 1 unresolved externals

God that error message is cryptic... Thank you for all of that oh so useful information Microsoft/Visual Studio!


I know the inline keyword is just a "hint" to the compiler and probably has no real value here, but it still shouldn't break the code!

Why is this happening?

like image 208
tjwrona1992 Avatar asked Nov 25 '15 16:11

tjwrona1992


1 Answers

I am not a language lawyer, so I can't tell if the compiler behaviour is legitimate or not. Yet, I can explain what is happening.

When you are marking your functions inline, you are not hinting the compiler that it can inline this function. Since over 10 years compilers do not need your hint here. They know when to inline. Instead, what you do, you indicate the function definition to be local for every translation unit it is included in. For this definition should be available.

Effectively what you said is that name() definition should be local for every .cpp file, but you didn't make it available for every .cpp file! I still believe the compiler could give a warning here.

like image 181
SergeyA Avatar answered Sep 18 '22 14:09

SergeyA