What is the point of a constraint expression on a non-templated function?What is a lambda expression in C++11?Function template signaturesWhy does the order of template argument substitution matter?What are constrained templates?Specifying a concept for a type that has a member function template using Concepts LiteMust template argument functions be treated as potentially constexpr?Reference as a non-type template argumentPointer to function vs function as template non-type parameterWith P1141R1 voted in, how many types are deduced from multiple deduced parameters with the same constraint?What is the purpose of the declaration “template auto A::f(int t) -> decltype(t + g())”

What details should I consider before agreeing for part of my salary to be 'retained' by employer?

At which point can a system be compromised when downloading archived data from an untrusted source?

How possible is a successful landing just with 1 wing?

Improve quality of image bars

Did 007 exist before James Bond?

Why doesn't philosophy have higher standards for its arguments?

Vienna To Graz By Rail

What is the meaning of [[:space:]] in bash?

Kepler space telescope undetected planets

How to remove the first colon ':' from a timestamp?

Is it rude to refer to janitors as 'floor people'?

How to have a continuous player experience in a setting that's likely to favor TPKs?

How can a drink contain 1.8 kcal energy while 0 g fat/carbs/protein?

How many bits in the resultant hash will change, if the x bits are changed in its the original input?

Interviewing with an unmentioned 9 months of sick leave taken during a job

Increasing muscle power without increasing volume

Is passive Investigation essentially truesight against illusions?

Does the Intel 8085 CPU use real memory addresses?

Should I be able to keep my company purchased standing desk when I leave my job?

How can electric field be defined as force per charge, if the charge makes its own, singular electric field?

How could a medieval fortress manage large groups of migrants and travelers?

Intel 8080-based home computers

Alternator dying so junk car?

Why do so many pure math PhD students drop out or leave academia, compared to applied mathematics PhDs?



What is the point of a constraint expression on a non-templated function?


What is a lambda expression in C++11?Function template signaturesWhy does the order of template argument substitution matter?What are constrained templates?Specifying a concept for a type that has a member function template using Concepts LiteMust template argument functions be treated as potentially constexpr?Reference as a non-type template argumentPointer to function vs function as template non-type parameterWith P1141R1 voted in, how many types are deduced from multiple deduced parameters with the same constraint?What is the purpose of the declaration “template auto A::f(int t) -> decltype(t + g())”






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








9















[temp.constr.decl] says that we can constrain a template or a function with a constraint expression.



Declarators [dcl.decl] tells us that, for functions, we may add an optional trailing requires clause to constrain it, and the standard draft n4820 even gives these (seemingly pointless) examples:



void f1(int a) requires true;
auto f2(int a) -> bool requires true;


I understand that constraining a template or a concept is useful, but I fail to see how these constraints are useful for non-templated functions. What's the point of constraining a non-templated function?










share|improve this question




























    9















    [temp.constr.decl] says that we can constrain a template or a function with a constraint expression.



    Declarators [dcl.decl] tells us that, for functions, we may add an optional trailing requires clause to constrain it, and the standard draft n4820 even gives these (seemingly pointless) examples:



    void f1(int a) requires true;
    auto f2(int a) -> bool requires true;


    I understand that constraining a template or a concept is useful, but I fail to see how these constraints are useful for non-templated functions. What's the point of constraining a non-templated function?










    share|improve this question
























      9












      9








      9


      4






      [temp.constr.decl] says that we can constrain a template or a function with a constraint expression.



      Declarators [dcl.decl] tells us that, for functions, we may add an optional trailing requires clause to constrain it, and the standard draft n4820 even gives these (seemingly pointless) examples:



      void f1(int a) requires true;
      auto f2(int a) -> bool requires true;


      I understand that constraining a template or a concept is useful, but I fail to see how these constraints are useful for non-templated functions. What's the point of constraining a non-templated function?










      share|improve this question














      [temp.constr.decl] says that we can constrain a template or a function with a constraint expression.



      Declarators [dcl.decl] tells us that, for functions, we may add an optional trailing requires clause to constrain it, and the standard draft n4820 even gives these (seemingly pointless) examples:



      void f1(int a) requires true;
      auto f2(int a) -> bool requires true;


      I understand that constraining a template or a concept is useful, but I fail to see how these constraints are useful for non-templated functions. What's the point of constraining a non-templated function?







      c++ language-lawyer c++20






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 8 hours ago









      AndyGAndyG

      28.1k7 gold badges74 silver badges106 bronze badges




      28.1k7 gold badges74 silver badges106 bronze badges






















          2 Answers
          2






          active

          oldest

          votes


















          4














          One of the main points of constraining non-template functions is to be able to write constraints to non-template members of template classes. For example, you might have some type like this:



          template<typename T>
          class value

          public:
          value(const T& t);
          value(T&& t);

          private:
          T t_;
          ;


          Now, you want value to be copyable/moveable from T. But really, you want it to be copyable/moveable from T only as far as T itself is copyable/moveable. So, how do you do it?



          Pre-constraints, you would need to write a bunch of meta-programming hackery. Maybe you make these constructors templates, which require that the given type U is the same as T, in addition to the copy/move requirement. Or you might have to write a base class that you inherit from, which has different specializations based on the copy/moveability of T.



          Post-constraints, you do this:



          class value

          public:
          value(const T& t) requires is_copy_constructible_v<T> : t_(t)
          value(T&& t) requires is_move_constructible_v<T> : t_(std::move(t))

          private:
          T t_;
          ;


          No hackery. No applying templates to functions that don't need to be templates. It just works, and its easy for the user to understand what is going on.



          This is especially important for functions which cannot be templates. In order for a constructor to be considered a copy or move constructor, it cannot be a template. Same goes for copy/move assignment operators. But such things can have constraints.






          share|improve this answer






























            11














            Just as a concept consider the following example



            #include <iostream>

            void f( long x ) requires ( sizeof( long ) == sizeof( int ) )

            std::cout << "Bye " << x << 'n';


            void f( long long x ) requires ( sizeof( long ) == sizeof( long long ) )

            std::cout << "Hello " << x << 'n';


            int main()

            f( 0l );



            If sizeof( long ) == sizeof( long long ) then the program output will be



            Hello 0


            Otherwise



            Bye 0


            For example you can use such an approach in a function that calculates the factorial to restrict the number of a loop iterations or to throw an exception.



            Here is a demonstrative program.



            #include <iostream>
            #include <stdexcept>

            unsigned long factorial( unsigned long n ) noexcept( false )
            requires ( sizeof( unsigned long ) == sizeof( unsigned int ) )

            const unsigned long MAX_STEPS = 12;

            if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

            unsigned long f = 1;

            for ( unsigned long i = 1; i < n; i++ ) f *= ( i + 1 );

            return f;


            unsigned long long factorial( unsigned long long n ) noexcept( false )
            requires ( sizeof( unsigned long ) == sizeof( unsigned long long ) )

            const unsigned long long MAX_STEPS = 20;

            if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

            unsigned long f = 1;

            for ( unsigned long long i = 1; i < n; i++ ) f *= ( i + 1 );

            return f;


            int main()

            unsigned long n = 20;

            try

            std::cout << factorial( n ) << 'n';

            catch ( const std::out_of_range &ex )

            std::cout << ex.what() << 'n';




            Its output might be either



            2432902008176640000


            or



            Too big value.





            share|improve this answer




















            • 1





              Very nice. Now we can uplift static asserts out of the function body and make it part of the signature.

              – NathanOliver
              8 hours ago






            • 1





              Indeed, or choose to write an overload instead of if constexpr

              – AndyG
              8 hours ago











            • I wish I could accept both answers because they're of such high quality, but I felt that NicolBolas' answer was more in line with what the feature is for. I'm sorry that you'll just have to settle for an upvote.

              – AndyG
              6 hours ago











            • @AndyG No problem. You are welcome.:)

              – Vlad from Moscow
              6 hours ago














            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%2f57078643%2fwhat-is-the-point-of-a-constraint-expression-on-a-non-templated-function%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









            4














            One of the main points of constraining non-template functions is to be able to write constraints to non-template members of template classes. For example, you might have some type like this:



            template<typename T>
            class value

            public:
            value(const T& t);
            value(T&& t);

            private:
            T t_;
            ;


            Now, you want value to be copyable/moveable from T. But really, you want it to be copyable/moveable from T only as far as T itself is copyable/moveable. So, how do you do it?



            Pre-constraints, you would need to write a bunch of meta-programming hackery. Maybe you make these constructors templates, which require that the given type U is the same as T, in addition to the copy/move requirement. Or you might have to write a base class that you inherit from, which has different specializations based on the copy/moveability of T.



            Post-constraints, you do this:



            class value

            public:
            value(const T& t) requires is_copy_constructible_v<T> : t_(t)
            value(T&& t) requires is_move_constructible_v<T> : t_(std::move(t))

            private:
            T t_;
            ;


            No hackery. No applying templates to functions that don't need to be templates. It just works, and its easy for the user to understand what is going on.



            This is especially important for functions which cannot be templates. In order for a constructor to be considered a copy or move constructor, it cannot be a template. Same goes for copy/move assignment operators. But such things can have constraints.






            share|improve this answer



























              4














              One of the main points of constraining non-template functions is to be able to write constraints to non-template members of template classes. For example, you might have some type like this:



              template<typename T>
              class value

              public:
              value(const T& t);
              value(T&& t);

              private:
              T t_;
              ;


              Now, you want value to be copyable/moveable from T. But really, you want it to be copyable/moveable from T only as far as T itself is copyable/moveable. So, how do you do it?



              Pre-constraints, you would need to write a bunch of meta-programming hackery. Maybe you make these constructors templates, which require that the given type U is the same as T, in addition to the copy/move requirement. Or you might have to write a base class that you inherit from, which has different specializations based on the copy/moveability of T.



              Post-constraints, you do this:



              class value

              public:
              value(const T& t) requires is_copy_constructible_v<T> : t_(t)
              value(T&& t) requires is_move_constructible_v<T> : t_(std::move(t))

              private:
              T t_;
              ;


              No hackery. No applying templates to functions that don't need to be templates. It just works, and its easy for the user to understand what is going on.



              This is especially important for functions which cannot be templates. In order for a constructor to be considered a copy or move constructor, it cannot be a template. Same goes for copy/move assignment operators. But such things can have constraints.






              share|improve this answer

























                4












                4








                4







                One of the main points of constraining non-template functions is to be able to write constraints to non-template members of template classes. For example, you might have some type like this:



                template<typename T>
                class value

                public:
                value(const T& t);
                value(T&& t);

                private:
                T t_;
                ;


                Now, you want value to be copyable/moveable from T. But really, you want it to be copyable/moveable from T only as far as T itself is copyable/moveable. So, how do you do it?



                Pre-constraints, you would need to write a bunch of meta-programming hackery. Maybe you make these constructors templates, which require that the given type U is the same as T, in addition to the copy/move requirement. Or you might have to write a base class that you inherit from, which has different specializations based on the copy/moveability of T.



                Post-constraints, you do this:



                class value

                public:
                value(const T& t) requires is_copy_constructible_v<T> : t_(t)
                value(T&& t) requires is_move_constructible_v<T> : t_(std::move(t))

                private:
                T t_;
                ;


                No hackery. No applying templates to functions that don't need to be templates. It just works, and its easy for the user to understand what is going on.



                This is especially important for functions which cannot be templates. In order for a constructor to be considered a copy or move constructor, it cannot be a template. Same goes for copy/move assignment operators. But such things can have constraints.






                share|improve this answer













                One of the main points of constraining non-template functions is to be able to write constraints to non-template members of template classes. For example, you might have some type like this:



                template<typename T>
                class value

                public:
                value(const T& t);
                value(T&& t);

                private:
                T t_;
                ;


                Now, you want value to be copyable/moveable from T. But really, you want it to be copyable/moveable from T only as far as T itself is copyable/moveable. So, how do you do it?



                Pre-constraints, you would need to write a bunch of meta-programming hackery. Maybe you make these constructors templates, which require that the given type U is the same as T, in addition to the copy/move requirement. Or you might have to write a base class that you inherit from, which has different specializations based on the copy/moveability of T.



                Post-constraints, you do this:



                class value

                public:
                value(const T& t) requires is_copy_constructible_v<T> : t_(t)
                value(T&& t) requires is_move_constructible_v<T> : t_(std::move(t))

                private:
                T t_;
                ;


                No hackery. No applying templates to functions that don't need to be templates. It just works, and its easy for the user to understand what is going on.



                This is especially important for functions which cannot be templates. In order for a constructor to be considered a copy or move constructor, it cannot be a template. Same goes for copy/move assignment operators. But such things can have constraints.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 8 hours ago









                Nicol BolasNicol Bolas

                302k37 gold badges506 silver badges682 bronze badges




                302k37 gold badges506 silver badges682 bronze badges























                    11














                    Just as a concept consider the following example



                    #include <iostream>

                    void f( long x ) requires ( sizeof( long ) == sizeof( int ) )

                    std::cout << "Bye " << x << 'n';


                    void f( long long x ) requires ( sizeof( long ) == sizeof( long long ) )

                    std::cout << "Hello " << x << 'n';


                    int main()

                    f( 0l );



                    If sizeof( long ) == sizeof( long long ) then the program output will be



                    Hello 0


                    Otherwise



                    Bye 0


                    For example you can use such an approach in a function that calculates the factorial to restrict the number of a loop iterations or to throw an exception.



                    Here is a demonstrative program.



                    #include <iostream>
                    #include <stdexcept>

                    unsigned long factorial( unsigned long n ) noexcept( false )
                    requires ( sizeof( unsigned long ) == sizeof( unsigned int ) )

                    const unsigned long MAX_STEPS = 12;

                    if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

                    unsigned long f = 1;

                    for ( unsigned long i = 1; i < n; i++ ) f *= ( i + 1 );

                    return f;


                    unsigned long long factorial( unsigned long long n ) noexcept( false )
                    requires ( sizeof( unsigned long ) == sizeof( unsigned long long ) )

                    const unsigned long long MAX_STEPS = 20;

                    if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

                    unsigned long f = 1;

                    for ( unsigned long long i = 1; i < n; i++ ) f *= ( i + 1 );

                    return f;


                    int main()

                    unsigned long n = 20;

                    try

                    std::cout << factorial( n ) << 'n';

                    catch ( const std::out_of_range &ex )

                    std::cout << ex.what() << 'n';




                    Its output might be either



                    2432902008176640000


                    or



                    Too big value.





                    share|improve this answer




















                    • 1





                      Very nice. Now we can uplift static asserts out of the function body and make it part of the signature.

                      – NathanOliver
                      8 hours ago






                    • 1





                      Indeed, or choose to write an overload instead of if constexpr

                      – AndyG
                      8 hours ago











                    • I wish I could accept both answers because they're of such high quality, but I felt that NicolBolas' answer was more in line with what the feature is for. I'm sorry that you'll just have to settle for an upvote.

                      – AndyG
                      6 hours ago











                    • @AndyG No problem. You are welcome.:)

                      – Vlad from Moscow
                      6 hours ago
















                    11














                    Just as a concept consider the following example



                    #include <iostream>

                    void f( long x ) requires ( sizeof( long ) == sizeof( int ) )

                    std::cout << "Bye " << x << 'n';


                    void f( long long x ) requires ( sizeof( long ) == sizeof( long long ) )

                    std::cout << "Hello " << x << 'n';


                    int main()

                    f( 0l );



                    If sizeof( long ) == sizeof( long long ) then the program output will be



                    Hello 0


                    Otherwise



                    Bye 0


                    For example you can use such an approach in a function that calculates the factorial to restrict the number of a loop iterations or to throw an exception.



                    Here is a demonstrative program.



                    #include <iostream>
                    #include <stdexcept>

                    unsigned long factorial( unsigned long n ) noexcept( false )
                    requires ( sizeof( unsigned long ) == sizeof( unsigned int ) )

                    const unsigned long MAX_STEPS = 12;

                    if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

                    unsigned long f = 1;

                    for ( unsigned long i = 1; i < n; i++ ) f *= ( i + 1 );

                    return f;


                    unsigned long long factorial( unsigned long long n ) noexcept( false )
                    requires ( sizeof( unsigned long ) == sizeof( unsigned long long ) )

                    const unsigned long long MAX_STEPS = 20;

                    if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

                    unsigned long f = 1;

                    for ( unsigned long long i = 1; i < n; i++ ) f *= ( i + 1 );

                    return f;


                    int main()

                    unsigned long n = 20;

                    try

                    std::cout << factorial( n ) << 'n';

                    catch ( const std::out_of_range &ex )

                    std::cout << ex.what() << 'n';




                    Its output might be either



                    2432902008176640000


                    or



                    Too big value.





                    share|improve this answer




















                    • 1





                      Very nice. Now we can uplift static asserts out of the function body and make it part of the signature.

                      – NathanOliver
                      8 hours ago






                    • 1





                      Indeed, or choose to write an overload instead of if constexpr

                      – AndyG
                      8 hours ago











                    • I wish I could accept both answers because they're of such high quality, but I felt that NicolBolas' answer was more in line with what the feature is for. I'm sorry that you'll just have to settle for an upvote.

                      – AndyG
                      6 hours ago











                    • @AndyG No problem. You are welcome.:)

                      – Vlad from Moscow
                      6 hours ago














                    11












                    11








                    11







                    Just as a concept consider the following example



                    #include <iostream>

                    void f( long x ) requires ( sizeof( long ) == sizeof( int ) )

                    std::cout << "Bye " << x << 'n';


                    void f( long long x ) requires ( sizeof( long ) == sizeof( long long ) )

                    std::cout << "Hello " << x << 'n';


                    int main()

                    f( 0l );



                    If sizeof( long ) == sizeof( long long ) then the program output will be



                    Hello 0


                    Otherwise



                    Bye 0


                    For example you can use such an approach in a function that calculates the factorial to restrict the number of a loop iterations or to throw an exception.



                    Here is a demonstrative program.



                    #include <iostream>
                    #include <stdexcept>

                    unsigned long factorial( unsigned long n ) noexcept( false )
                    requires ( sizeof( unsigned long ) == sizeof( unsigned int ) )

                    const unsigned long MAX_STEPS = 12;

                    if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

                    unsigned long f = 1;

                    for ( unsigned long i = 1; i < n; i++ ) f *= ( i + 1 );

                    return f;


                    unsigned long long factorial( unsigned long long n ) noexcept( false )
                    requires ( sizeof( unsigned long ) == sizeof( unsigned long long ) )

                    const unsigned long long MAX_STEPS = 20;

                    if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

                    unsigned long f = 1;

                    for ( unsigned long long i = 1; i < n; i++ ) f *= ( i + 1 );

                    return f;


                    int main()

                    unsigned long n = 20;

                    try

                    std::cout << factorial( n ) << 'n';

                    catch ( const std::out_of_range &ex )

                    std::cout << ex.what() << 'n';




                    Its output might be either



                    2432902008176640000


                    or



                    Too big value.





                    share|improve this answer















                    Just as a concept consider the following example



                    #include <iostream>

                    void f( long x ) requires ( sizeof( long ) == sizeof( int ) )

                    std::cout << "Bye " << x << 'n';


                    void f( long long x ) requires ( sizeof( long ) == sizeof( long long ) )

                    std::cout << "Hello " << x << 'n';


                    int main()

                    f( 0l );



                    If sizeof( long ) == sizeof( long long ) then the program output will be



                    Hello 0


                    Otherwise



                    Bye 0


                    For example you can use such an approach in a function that calculates the factorial to restrict the number of a loop iterations or to throw an exception.



                    Here is a demonstrative program.



                    #include <iostream>
                    #include <stdexcept>

                    unsigned long factorial( unsigned long n ) noexcept( false )
                    requires ( sizeof( unsigned long ) == sizeof( unsigned int ) )

                    const unsigned long MAX_STEPS = 12;

                    if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

                    unsigned long f = 1;

                    for ( unsigned long i = 1; i < n; i++ ) f *= ( i + 1 );

                    return f;


                    unsigned long long factorial( unsigned long long n ) noexcept( false )
                    requires ( sizeof( unsigned long ) == sizeof( unsigned long long ) )

                    const unsigned long long MAX_STEPS = 20;

                    if ( MAX_STEPS < n ) throw std::out_of_range( "Too big value." );

                    unsigned long f = 1;

                    for ( unsigned long long i = 1; i < n; i++ ) f *= ( i + 1 );

                    return f;


                    int main()

                    unsigned long n = 20;

                    try

                    std::cout << factorial( n ) << 'n';

                    catch ( const std::out_of_range &ex )

                    std::cout << ex.what() << 'n';




                    Its output might be either



                    2432902008176640000


                    or



                    Too big value.






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited 7 hours ago

























                    answered 8 hours ago









                    Vlad from MoscowVlad from Moscow

                    145k13 gold badges88 silver badges186 bronze badges




                    145k13 gold badges88 silver badges186 bronze badges







                    • 1





                      Very nice. Now we can uplift static asserts out of the function body and make it part of the signature.

                      – NathanOliver
                      8 hours ago






                    • 1





                      Indeed, or choose to write an overload instead of if constexpr

                      – AndyG
                      8 hours ago











                    • I wish I could accept both answers because they're of such high quality, but I felt that NicolBolas' answer was more in line with what the feature is for. I'm sorry that you'll just have to settle for an upvote.

                      – AndyG
                      6 hours ago











                    • @AndyG No problem. You are welcome.:)

                      – Vlad from Moscow
                      6 hours ago













                    • 1





                      Very nice. Now we can uplift static asserts out of the function body and make it part of the signature.

                      – NathanOliver
                      8 hours ago






                    • 1





                      Indeed, or choose to write an overload instead of if constexpr

                      – AndyG
                      8 hours ago











                    • I wish I could accept both answers because they're of such high quality, but I felt that NicolBolas' answer was more in line with what the feature is for. I'm sorry that you'll just have to settle for an upvote.

                      – AndyG
                      6 hours ago











                    • @AndyG No problem. You are welcome.:)

                      – Vlad from Moscow
                      6 hours ago








                    1




                    1





                    Very nice. Now we can uplift static asserts out of the function body and make it part of the signature.

                    – NathanOliver
                    8 hours ago





                    Very nice. Now we can uplift static asserts out of the function body and make it part of the signature.

                    – NathanOliver
                    8 hours ago




                    1




                    1





                    Indeed, or choose to write an overload instead of if constexpr

                    – AndyG
                    8 hours ago





                    Indeed, or choose to write an overload instead of if constexpr

                    – AndyG
                    8 hours ago













                    I wish I could accept both answers because they're of such high quality, but I felt that NicolBolas' answer was more in line with what the feature is for. I'm sorry that you'll just have to settle for an upvote.

                    – AndyG
                    6 hours ago





                    I wish I could accept both answers because they're of such high quality, but I felt that NicolBolas' answer was more in line with what the feature is for. I'm sorry that you'll just have to settle for an upvote.

                    – AndyG
                    6 hours ago













                    @AndyG No problem. You are welcome.:)

                    – Vlad from Moscow
                    6 hours ago






                    @AndyG No problem. You are welcome.:)

                    – Vlad from Moscow
                    6 hours ago


















                    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%2f57078643%2fwhat-is-the-point-of-a-constraint-expression-on-a-non-templated-function%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

                    Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

                    Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

                    Ласкавець круглолистий Зміст Опис | Поширення | Галерея | Примітки | Посилання | Навігаційне меню58171138361-22960890446Bupleurum rotundifoliumEuro+Med PlantbasePlants of the World Online — Kew ScienceGermplasm Resources Information Network (GRIN)Ласкавецькн. VI : Літери Ком — Левиправивши або дописавши її