Inconsistent behaviour across compilers in regard to instantiation of a template in a discarded if...












17















I am trying to understand whether the snippet below should compile according to The Standard or not. When I try to compile it with latest version of three major compilers, the following occurs:





  • Clang (version 7.0.0, with -std=c++17 flag): compiles fine;


  • GCC (version 8.2, with -std=c++17 flag): also compiles fine;


  • MSVC (version 19.16, with /std:c++17 flag): compiler error (see below).


The error occurs because the MSVC compiler seemingly tries to instantiate std::optional<void> despite the fact that the code is discarded. GCC and Clang don't seem to do that.



Does The Standard clearly define what should occur in this case?



#include <optional>  
#include <type_traits>
template<typename T, typename... Args>
struct Bar
{
void foo(Args... args)
{
if constexpr(!std::is_same_v<T, void>) // false
{
// MSVC compiler error occurs because of the line below; no error occurs when compiling with GCC and Clang
std::optional<T> val;
}
}
};
int main(int argc, char** argv)
{
Bar<void, int> inst;
inst.foo(1);
return 0;
}


Error by MSVC:




C:/msvc/v19_16/includeoptional(87): error C2182: '_Value': illegal use of type 'void'

C:/msvc/v19_16/includeoptional(128): note: see reference to class template instantiation 'std::_Optional_destruct_base<_Ty,false>' being compiled
with
[
_Ty=void
]



Live demo










share|improve this question




















  • 2





    Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.

    – Dan M.
    2 days ago











  • For what it's worth: the motivation of if constexpr was more or less exactly to make examples like that compile.

    – Barry
    2 days ago
















17















I am trying to understand whether the snippet below should compile according to The Standard or not. When I try to compile it with latest version of three major compilers, the following occurs:





  • Clang (version 7.0.0, with -std=c++17 flag): compiles fine;


  • GCC (version 8.2, with -std=c++17 flag): also compiles fine;


  • MSVC (version 19.16, with /std:c++17 flag): compiler error (see below).


The error occurs because the MSVC compiler seemingly tries to instantiate std::optional<void> despite the fact that the code is discarded. GCC and Clang don't seem to do that.



Does The Standard clearly define what should occur in this case?



#include <optional>  
#include <type_traits>
template<typename T, typename... Args>
struct Bar
{
void foo(Args... args)
{
if constexpr(!std::is_same_v<T, void>) // false
{
// MSVC compiler error occurs because of the line below; no error occurs when compiling with GCC and Clang
std::optional<T> val;
}
}
};
int main(int argc, char** argv)
{
Bar<void, int> inst;
inst.foo(1);
return 0;
}


Error by MSVC:




C:/msvc/v19_16/includeoptional(87): error C2182: '_Value': illegal use of type 'void'

C:/msvc/v19_16/includeoptional(128): note: see reference to class template instantiation 'std::_Optional_destruct_base<_Ty,false>' being compiled
with
[
_Ty=void
]



Live demo










share|improve this question




















  • 2





    Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.

    – Dan M.
    2 days ago











  • For what it's worth: the motivation of if constexpr was more or less exactly to make examples like that compile.

    – Barry
    2 days ago














17












17








17








I am trying to understand whether the snippet below should compile according to The Standard or not. When I try to compile it with latest version of three major compilers, the following occurs:





  • Clang (version 7.0.0, with -std=c++17 flag): compiles fine;


  • GCC (version 8.2, with -std=c++17 flag): also compiles fine;


  • MSVC (version 19.16, with /std:c++17 flag): compiler error (see below).


The error occurs because the MSVC compiler seemingly tries to instantiate std::optional<void> despite the fact that the code is discarded. GCC and Clang don't seem to do that.



Does The Standard clearly define what should occur in this case?



#include <optional>  
#include <type_traits>
template<typename T, typename... Args>
struct Bar
{
void foo(Args... args)
{
if constexpr(!std::is_same_v<T, void>) // false
{
// MSVC compiler error occurs because of the line below; no error occurs when compiling with GCC and Clang
std::optional<T> val;
}
}
};
int main(int argc, char** argv)
{
Bar<void, int> inst;
inst.foo(1);
return 0;
}


Error by MSVC:




C:/msvc/v19_16/includeoptional(87): error C2182: '_Value': illegal use of type 'void'

C:/msvc/v19_16/includeoptional(128): note: see reference to class template instantiation 'std::_Optional_destruct_base<_Ty,false>' being compiled
with
[
_Ty=void
]



Live demo










share|improve this question
















I am trying to understand whether the snippet below should compile according to The Standard or not. When I try to compile it with latest version of three major compilers, the following occurs:





  • Clang (version 7.0.0, with -std=c++17 flag): compiles fine;


  • GCC (version 8.2, with -std=c++17 flag): also compiles fine;


  • MSVC (version 19.16, with /std:c++17 flag): compiler error (see below).


The error occurs because the MSVC compiler seemingly tries to instantiate std::optional<void> despite the fact that the code is discarded. GCC and Clang don't seem to do that.



Does The Standard clearly define what should occur in this case?



#include <optional>  
#include <type_traits>
template<typename T, typename... Args>
struct Bar
{
void foo(Args... args)
{
if constexpr(!std::is_same_v<T, void>) // false
{
// MSVC compiler error occurs because of the line below; no error occurs when compiling with GCC and Clang
std::optional<T> val;
}
}
};
int main(int argc, char** argv)
{
Bar<void, int> inst;
inst.foo(1);
return 0;
}


Error by MSVC:




C:/msvc/v19_16/includeoptional(87): error C2182: '_Value': illegal use of type 'void'

C:/msvc/v19_16/includeoptional(128): note: see reference to class template instantiation 'std::_Optional_destruct_base<_Ty,false>' being compiled
with
[
_Ty=void
]



Live demo







c++ language-lawyer c++17






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago









YSC

21k34899




21k34899










asked 2 days ago









NejcNejc

763212




763212








  • 2





    Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.

    – Dan M.
    2 days ago











  • For what it's worth: the motivation of if constexpr was more or less exactly to make examples like that compile.

    – Barry
    2 days ago














  • 2





    Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.

    – Dan M.
    2 days ago











  • For what it's worth: the motivation of if constexpr was more or less exactly to make examples like that compile.

    – Barry
    2 days ago








2




2





Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.

– Dan M.
2 days ago





Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.

– Dan M.
2 days ago













For what it's worth: the motivation of if constexpr was more or less exactly to make examples like that compile.

– Barry
2 days ago





For what it's worth: the motivation of if constexpr was more or less exactly to make examples like that compile.

– Barry
2 days ago












2 Answers
2






active

oldest

votes


















18














Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.





if constexpr is standardized in [stmt.if]/2:




If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.




This applies.




If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].




It also applies, making in your program { std::optional<T> val; } a discarded statement.




During the instantiation of an enclosing templated entity (ndYSC Bar<void, int>), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.







share|improve this answer


























  • I downloaded Visual Studio 2019 Preview and tried to compile the code with the compiler version 19.20 that shipped with it. The issue from the bug report which you mentioned is indeed solved ... but unfortunately my code snippet still does not compile (I get the same compiler errors as before).

    – Nejc
    yesterday








  • 1





    I created a bug report: developercommunity.visualstudio.com/content/problem/425475/…

    – Nejc
    yesterday



















5














Along with @YSC's answer, also relevant is [temp.inst]/10:




An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.







share|improve this answer























    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%2f54126957%2finconsistent-behaviour-across-compilers-in-regard-to-instantiation-of-a-template%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    18














    Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.





    if constexpr is standardized in [stmt.if]/2:




    If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.




    This applies.




    If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].




    It also applies, making in your program { std::optional<T> val; } a discarded statement.




    During the instantiation of an enclosing templated entity (ndYSC Bar<void, int>), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.







    share|improve this answer


























    • I downloaded Visual Studio 2019 Preview and tried to compile the code with the compiler version 19.20 that shipped with it. The issue from the bug report which you mentioned is indeed solved ... but unfortunately my code snippet still does not compile (I get the same compiler errors as before).

      – Nejc
      yesterday








    • 1





      I created a bug report: developercommunity.visualstudio.com/content/problem/425475/…

      – Nejc
      yesterday
















    18














    Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.





    if constexpr is standardized in [stmt.if]/2:




    If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.




    This applies.




    If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].




    It also applies, making in your program { std::optional<T> val; } a discarded statement.




    During the instantiation of an enclosing templated entity (ndYSC Bar<void, int>), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.







    share|improve this answer


























    • I downloaded Visual Studio 2019 Preview and tried to compile the code with the compiler version 19.20 that shipped with it. The issue from the bug report which you mentioned is indeed solved ... but unfortunately my code snippet still does not compile (I get the same compiler errors as before).

      – Nejc
      yesterday








    • 1





      I created a bug report: developercommunity.visualstudio.com/content/problem/425475/…

      – Nejc
      yesterday














    18












    18








    18







    Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.





    if constexpr is standardized in [stmt.if]/2:




    If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.




    This applies.




    If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].




    It also applies, making in your program { std::optional<T> val; } a discarded statement.




    During the instantiation of an enclosing templated entity (ndYSC Bar<void, int>), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.







    share|improve this answer















    Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.





    if constexpr is standardized in [stmt.if]/2:




    If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.




    This applies.




    If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].




    It also applies, making in your program { std::optional<T> val; } a discarded statement.




    During the instantiation of an enclosing templated entity (ndYSC Bar<void, int>), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.








    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 2 days ago

























    answered 2 days ago









    YSCYSC

    21k34899




    21k34899













    • I downloaded Visual Studio 2019 Preview and tried to compile the code with the compiler version 19.20 that shipped with it. The issue from the bug report which you mentioned is indeed solved ... but unfortunately my code snippet still does not compile (I get the same compiler errors as before).

      – Nejc
      yesterday








    • 1





      I created a bug report: developercommunity.visualstudio.com/content/problem/425475/…

      – Nejc
      yesterday



















    • I downloaded Visual Studio 2019 Preview and tried to compile the code with the compiler version 19.20 that shipped with it. The issue from the bug report which you mentioned is indeed solved ... but unfortunately my code snippet still does not compile (I get the same compiler errors as before).

      – Nejc
      yesterday








    • 1





      I created a bug report: developercommunity.visualstudio.com/content/problem/425475/…

      – Nejc
      yesterday

















    I downloaded Visual Studio 2019 Preview and tried to compile the code with the compiler version 19.20 that shipped with it. The issue from the bug report which you mentioned is indeed solved ... but unfortunately my code snippet still does not compile (I get the same compiler errors as before).

    – Nejc
    yesterday







    I downloaded Visual Studio 2019 Preview and tried to compile the code with the compiler version 19.20 that shipped with it. The issue from the bug report which you mentioned is indeed solved ... but unfortunately my code snippet still does not compile (I get the same compiler errors as before).

    – Nejc
    yesterday






    1




    1





    I created a bug report: developercommunity.visualstudio.com/content/problem/425475/…

    – Nejc
    yesterday





    I created a bug report: developercommunity.visualstudio.com/content/problem/425475/…

    – Nejc
    yesterday













    5














    Along with @YSC's answer, also relevant is [temp.inst]/10:




    An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.







    share|improve this answer




























      5














      Along with @YSC's answer, also relevant is [temp.inst]/10:




      An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.







      share|improve this answer


























        5












        5








        5







        Along with @YSC's answer, also relevant is [temp.inst]/10:




        An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.







        share|improve this answer













        Along with @YSC's answer, also relevant is [temp.inst]/10:




        An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.








        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 2 days ago









        P.WP.W

        12k3842




        12k3842






























            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%2f54126957%2finconsistent-behaviour-across-compilers-in-regard-to-instantiation-of-a-template%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

            1300-talet

            1300-talet

            Display a custom attribute below product name in the front-end Magento 1.9.3.8