Template parameter type is treated as complete by the compiler, but its definition isn't yet visible












6















Assume I have the following code snippet:



template <class T>
class Bar
{
// static_assert(sizeof(T) > 0); // (1)
public:
void method()
{
static_assert(sizeof(T) > 0); // (2)
}
};

class Foo; // (3)

template class Bar<Foo>; // (4)

class Foo{}; // (5)


If we uncomment the line (1), we get a compile-time error "incomplete type T", and it seems to be clear: class Bar instantiation is launched by (4), and at that point class Foo is only forward-declared by (3) and not yet defined by (5).



But if the line (1) is commented out, then this code compiles with no errors, and it confuses me: (4) is an explicit template instantiation definition and it forces the compiler to generate void method() code, and line (2) should also generate the same error, since the definition of Foo is made later in (5).



What do I miss, why does the code from the snippet compiles?



UPDATE: Code compiles under GCC 8.2.0 and MSVC 19.16.27025.1, but under Clang 7.0.0 it gives an "incomplete type" error.










share|improve this question

























  • Compiles with what tool chain (because it pukes as-is with vc++ (19.00.24215.1) ? Include that in your question.

    – WhozCraig
    Jan 1 at 18:05













  • @WhozCraig Thanks, I added description. It turns out that clang doesn't compile this.

    – undermind
    Jan 1 at 18:57
















6















Assume I have the following code snippet:



template <class T>
class Bar
{
// static_assert(sizeof(T) > 0); // (1)
public:
void method()
{
static_assert(sizeof(T) > 0); // (2)
}
};

class Foo; // (3)

template class Bar<Foo>; // (4)

class Foo{}; // (5)


If we uncomment the line (1), we get a compile-time error "incomplete type T", and it seems to be clear: class Bar instantiation is launched by (4), and at that point class Foo is only forward-declared by (3) and not yet defined by (5).



But if the line (1) is commented out, then this code compiles with no errors, and it confuses me: (4) is an explicit template instantiation definition and it forces the compiler to generate void method() code, and line (2) should also generate the same error, since the definition of Foo is made later in (5).



What do I miss, why does the code from the snippet compiles?



UPDATE: Code compiles under GCC 8.2.0 and MSVC 19.16.27025.1, but under Clang 7.0.0 it gives an "incomplete type" error.










share|improve this question

























  • Compiles with what tool chain (because it pukes as-is with vc++ (19.00.24215.1) ? Include that in your question.

    – WhozCraig
    Jan 1 at 18:05













  • @WhozCraig Thanks, I added description. It turns out that clang doesn't compile this.

    – undermind
    Jan 1 at 18:57














6












6








6


0






Assume I have the following code snippet:



template <class T>
class Bar
{
// static_assert(sizeof(T) > 0); // (1)
public:
void method()
{
static_assert(sizeof(T) > 0); // (2)
}
};

class Foo; // (3)

template class Bar<Foo>; // (4)

class Foo{}; // (5)


If we uncomment the line (1), we get a compile-time error "incomplete type T", and it seems to be clear: class Bar instantiation is launched by (4), and at that point class Foo is only forward-declared by (3) and not yet defined by (5).



But if the line (1) is commented out, then this code compiles with no errors, and it confuses me: (4) is an explicit template instantiation definition and it forces the compiler to generate void method() code, and line (2) should also generate the same error, since the definition of Foo is made later in (5).



What do I miss, why does the code from the snippet compiles?



UPDATE: Code compiles under GCC 8.2.0 and MSVC 19.16.27025.1, but under Clang 7.0.0 it gives an "incomplete type" error.










share|improve this question
















Assume I have the following code snippet:



template <class T>
class Bar
{
// static_assert(sizeof(T) > 0); // (1)
public:
void method()
{
static_assert(sizeof(T) > 0); // (2)
}
};

class Foo; // (3)

template class Bar<Foo>; // (4)

class Foo{}; // (5)


If we uncomment the line (1), we get a compile-time error "incomplete type T", and it seems to be clear: class Bar instantiation is launched by (4), and at that point class Foo is only forward-declared by (3) and not yet defined by (5).



But if the line (1) is commented out, then this code compiles with no errors, and it confuses me: (4) is an explicit template instantiation definition and it forces the compiler to generate void method() code, and line (2) should also generate the same error, since the definition of Foo is made later in (5).



What do I miss, why does the code from the snippet compiles?



UPDATE: Code compiles under GCC 8.2.0 and MSVC 19.16.27025.1, but under Clang 7.0.0 it gives an "incomplete type" error.







c++ templates incomplete-type template-instantiation






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 1 at 18:56







undermind

















asked Jan 1 at 17:50









undermindundermind

944521




944521













  • Compiles with what tool chain (because it pukes as-is with vc++ (19.00.24215.1) ? Include that in your question.

    – WhozCraig
    Jan 1 at 18:05













  • @WhozCraig Thanks, I added description. It turns out that clang doesn't compile this.

    – undermind
    Jan 1 at 18:57



















  • Compiles with what tool chain (because it pukes as-is with vc++ (19.00.24215.1) ? Include that in your question.

    – WhozCraig
    Jan 1 at 18:05













  • @WhozCraig Thanks, I added description. It turns out that clang doesn't compile this.

    – undermind
    Jan 1 at 18:57

















Compiles with what tool chain (because it pukes as-is with vc++ (19.00.24215.1) ? Include that in your question.

– WhozCraig
Jan 1 at 18:05







Compiles with what tool chain (because it pukes as-is with vc++ (19.00.24215.1) ? Include that in your question.

– WhozCraig
Jan 1 at 18:05















@WhozCraig Thanks, I added description. It turns out that clang doesn't compile this.

– undermind
Jan 1 at 18:57





@WhozCraig Thanks, I added description. It turns out that clang doesn't compile this.

– undermind
Jan 1 at 18:57












1 Answer
1






active

oldest

votes


















7














As per the standard goes, during implicit instantiation only the declaration of member functions are instantiated but not their definition.




[temp.inst]/2 - The implicit instantiation of a class template specialization causes




  • the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends ...




but it doesn't say the same about explicit instantiations. The whole class is instantiated which means that it instantiates the definition of method() and at that point Foo isn't complete.




[temp.explicit]/11 - An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.




clang rejects the code.






share|improve this answer


























  • Indeed, clang doesn't compile it (I updated question description). So, is it a correct behavior?

    – undermind
    Jan 1 at 19:04











  • @undermind - yes, clang is correct

    – Jans
    Jan 1 at 19:24











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53997632%2ftemplate-parameter-type-is-treated-as-complete-by-the-compiler-but-its-definiti%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









7














As per the standard goes, during implicit instantiation only the declaration of member functions are instantiated but not their definition.




[temp.inst]/2 - The implicit instantiation of a class template specialization causes




  • the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends ...




but it doesn't say the same about explicit instantiations. The whole class is instantiated which means that it instantiates the definition of method() and at that point Foo isn't complete.




[temp.explicit]/11 - An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.




clang rejects the code.






share|improve this answer


























  • Indeed, clang doesn't compile it (I updated question description). So, is it a correct behavior?

    – undermind
    Jan 1 at 19:04











  • @undermind - yes, clang is correct

    – Jans
    Jan 1 at 19:24
















7














As per the standard goes, during implicit instantiation only the declaration of member functions are instantiated but not their definition.




[temp.inst]/2 - The implicit instantiation of a class template specialization causes




  • the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends ...




but it doesn't say the same about explicit instantiations. The whole class is instantiated which means that it instantiates the definition of method() and at that point Foo isn't complete.




[temp.explicit]/11 - An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.




clang rejects the code.






share|improve this answer


























  • Indeed, clang doesn't compile it (I updated question description). So, is it a correct behavior?

    – undermind
    Jan 1 at 19:04











  • @undermind - yes, clang is correct

    – Jans
    Jan 1 at 19:24














7












7








7







As per the standard goes, during implicit instantiation only the declaration of member functions are instantiated but not their definition.




[temp.inst]/2 - The implicit instantiation of a class template specialization causes




  • the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends ...




but it doesn't say the same about explicit instantiations. The whole class is instantiated which means that it instantiates the definition of method() and at that point Foo isn't complete.




[temp.explicit]/11 - An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.




clang rejects the code.






share|improve this answer















As per the standard goes, during implicit instantiation only the declaration of member functions are instantiated but not their definition.




[temp.inst]/2 - The implicit instantiation of a class template specialization causes




  • the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends ...




but it doesn't say the same about explicit instantiations. The whole class is instantiated which means that it instantiates the definition of method() and at that point Foo isn't complete.




[temp.explicit]/11 - An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.




clang rejects the code.







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 2 at 1:08









Rakete1111

35k1083118




35k1083118










answered Jan 1 at 18:24









JansJans

9,02422635




9,02422635













  • Indeed, clang doesn't compile it (I updated question description). So, is it a correct behavior?

    – undermind
    Jan 1 at 19:04











  • @undermind - yes, clang is correct

    – Jans
    Jan 1 at 19:24



















  • Indeed, clang doesn't compile it (I updated question description). So, is it a correct behavior?

    – undermind
    Jan 1 at 19:04











  • @undermind - yes, clang is correct

    – Jans
    Jan 1 at 19:24

















Indeed, clang doesn't compile it (I updated question description). So, is it a correct behavior?

– undermind
Jan 1 at 19:04





Indeed, clang doesn't compile it (I updated question description). So, is it a correct behavior?

– undermind
Jan 1 at 19:04













@undermind - yes, clang is correct

– Jans
Jan 1 at 19:24





@undermind - yes, clang is correct

– Jans
Jan 1 at 19:24




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53997632%2ftemplate-parameter-type-is-treated-as-complete-by-the-compiler-but-its-definiti%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas