Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
134 views
in Technique[技术] by (71.8m points)

c++ - Out of line definition of template function vs in class

I wondered if there was any advantages of declaring templates function out of line vs in the class.

I'm trying to get a clear understanding of the pros and cons of the two syntax.

Here's an example:

Out of line:

template<typename T>
struct MyType {
    template<typename... Args>
    void test(Args...) const;
};

template<typename T>
template<typename... Args>
void MyType<T>::test(Args... args) const {
    // do things
}

Vs in class:

template<typename T>
struct MyType {
    template<typename... Args>
    void test(Args... args) const {
        // do things
    }
};

Are there language features that are easier to use with the first or second version? Does the first version would get in the way when using default template arguments or enable_if? I would like to see comparisons of how those two cases are playing with different language features like sfinae, and maybe potential future features (modules?).

Taking compiler specific behavior into account can be interesting too. I think MSVC needs inline in some places with the first code snippet, but I'm not sure.

EDIT: I know there is no difference on how these features works, that this is mostly a matter of taste. I want to see how both syntaxes plays with different techniques, and the advantage of one over the other. I see mostly answers that favors one over another, but I really want to get both sides. A more objective answer would be better.

question from:https://stackoverflow.com/questions/40381680/out-of-line-definition-of-template-function-vs-in-class

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Are there language features that are easier to use with the first or second version?

Quite trivial a case, but it's worth to be mentioned: specializations.

As an example, you can do this with out-of-line definition:

template<typename T>
struct MyType {
    template<typename... Args>
    void test(Args...) const;

    // Some other functions...
};

template<typename T>
template<typename... Args>
void MyType<T>::test(Args... args) const {
    // do things
}

// Out-of-line definition for all the other functions...

template<>
template<typename... Args>
void MyType<int>::test(Args... args) const {
    // do slightly different things in test
    // and in test only for MyType<int>
}

If you want to do the same with in-class definitions only, you have to duplicate the code for all the other functions of MyType (supposing test is the only function you want to specialize, of course).
As an example:

template<>
struct MyType<int> {
    template<typename... Args>
    void test(Args...) const {
        // Specialized function
    }

    // Copy-and-paste of all the other functions...
};

Of course, you can still mix in-class and out-of-line definitions to do that and you have the same amount of code of the full out-of-line version.
Anyway I assumed you are oriented towards full in-class and full out-of-line solutions, thus mixed ones are not viable.


Another thing that you can do with out-of-line class definitions and you cannot do with in-class definitions at all is function template specializations.
Of course, you can put the primary definition in-class, but all the specializations must be put out-of-line.

In this case, the answer to the above mentioned question is: there exist even features of the language that you cannot use with one of the version.

As an example, consider the following code:

struct S {
    template<typename>
    void f();
};

template<>
void S::f<int>() {}

int main() {
    S s;
    s.f<int>();
}

Suppose the designer of the class wants to provide an implementation for f only for a few specific types.
He simply can't do that with in-class definitions.


Finally, out-of-line definitions help to break circular dependencies.
This has been already mentioned in most of the other answers and it doesn't worth it to give another example.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...