Why does type aliasing determine whether output is L-value or R-value?











up vote
3
down vote

favorite












I created a struct with two static functions for testing purposes. The first instance of f is called when an l-value reference is passed. The second instance is called when an r-value is passed:



template <typename _Tp>
struct T {
static constexpr void f(_Tp&) { std::cout << "f(T&) is called!n"; }
static constexpr void f(_Tp&&) { std::cout << "f(T&&) is called!n"; }
};


When I was experimenting with strong types, I found out the first instance, T::f(_Tp&) was called when I attempted to create the strong type implicitly. Why is this? (See following)



using T_int = T<int>;

T_int::f(
typename strong_types::create_strong_type<int, struct tag>(5)()
); // calls f::(T&) (?)

using KG = typename strong_types::create_strong_type<double, struct KG_tag>;
T_int::f(KG(4.2)()); // calls f(T&&)


Note that operator() returns the value given through the constructor.



Feel free to ask if I need to elaborate.



EDIT: strong_types is a namespace. It exists among other things of the alias create_strong_type:



namespace strong_type {
template <typename T, typename tag>
using create_strong_type = Strong_Type<T, tag>;

...
}

...

template <typename T, typename tag>
struct Strong_Type {
constexpr explicit Strong_Type(const T& value) : _value(value) {}
constexpr explicit Strong_Type(T&& value) : _value(std::move(value)) {}

constexpr T& operator()() noexcept { return _value; }

private:
T _value;
};









share|improve this question




















  • 3




    what is strong_types ?
    – Piotr Skotnicki
    Nov 19 at 17:32










  • Sure, but is it a third party library ?
    – Piotr Skotnicki
    Nov 19 at 17:40










  • Oo, I am sorry for my misunderstanding. strong_types is a namespace I created myself.
    – Lourens Dijkstra
    Nov 19 at 17:41






  • 1




    Also unrelated: Identifiers beginning with underscore, followed by uppercase letter are reserved and you are not allowed to use them.
    – user10605163
    Nov 19 at 17:45






  • 1




    Please fix the typos in your edits, the identifiers do not match, e.g. strong_type vs strong_types and Strong_Type and probably Strong_Type should be part of the namespace and before create_strong_type?. It doesn't compile the way it is even if generously moving around code.
    – user10605163
    Nov 19 at 17:51

















up vote
3
down vote

favorite












I created a struct with two static functions for testing purposes. The first instance of f is called when an l-value reference is passed. The second instance is called when an r-value is passed:



template <typename _Tp>
struct T {
static constexpr void f(_Tp&) { std::cout << "f(T&) is called!n"; }
static constexpr void f(_Tp&&) { std::cout << "f(T&&) is called!n"; }
};


When I was experimenting with strong types, I found out the first instance, T::f(_Tp&) was called when I attempted to create the strong type implicitly. Why is this? (See following)



using T_int = T<int>;

T_int::f(
typename strong_types::create_strong_type<int, struct tag>(5)()
); // calls f::(T&) (?)

using KG = typename strong_types::create_strong_type<double, struct KG_tag>;
T_int::f(KG(4.2)()); // calls f(T&&)


Note that operator() returns the value given through the constructor.



Feel free to ask if I need to elaborate.



EDIT: strong_types is a namespace. It exists among other things of the alias create_strong_type:



namespace strong_type {
template <typename T, typename tag>
using create_strong_type = Strong_Type<T, tag>;

...
}

...

template <typename T, typename tag>
struct Strong_Type {
constexpr explicit Strong_Type(const T& value) : _value(value) {}
constexpr explicit Strong_Type(T&& value) : _value(std::move(value)) {}

constexpr T& operator()() noexcept { return _value; }

private:
T _value;
};









share|improve this question




















  • 3




    what is strong_types ?
    – Piotr Skotnicki
    Nov 19 at 17:32










  • Sure, but is it a third party library ?
    – Piotr Skotnicki
    Nov 19 at 17:40










  • Oo, I am sorry for my misunderstanding. strong_types is a namespace I created myself.
    – Lourens Dijkstra
    Nov 19 at 17:41






  • 1




    Also unrelated: Identifiers beginning with underscore, followed by uppercase letter are reserved and you are not allowed to use them.
    – user10605163
    Nov 19 at 17:45






  • 1




    Please fix the typos in your edits, the identifiers do not match, e.g. strong_type vs strong_types and Strong_Type and probably Strong_Type should be part of the namespace and before create_strong_type?. It doesn't compile the way it is even if generously moving around code.
    – user10605163
    Nov 19 at 17:51















up vote
3
down vote

favorite









up vote
3
down vote

favorite











I created a struct with two static functions for testing purposes. The first instance of f is called when an l-value reference is passed. The second instance is called when an r-value is passed:



template <typename _Tp>
struct T {
static constexpr void f(_Tp&) { std::cout << "f(T&) is called!n"; }
static constexpr void f(_Tp&&) { std::cout << "f(T&&) is called!n"; }
};


When I was experimenting with strong types, I found out the first instance, T::f(_Tp&) was called when I attempted to create the strong type implicitly. Why is this? (See following)



using T_int = T<int>;

T_int::f(
typename strong_types::create_strong_type<int, struct tag>(5)()
); // calls f::(T&) (?)

using KG = typename strong_types::create_strong_type<double, struct KG_tag>;
T_int::f(KG(4.2)()); // calls f(T&&)


Note that operator() returns the value given through the constructor.



Feel free to ask if I need to elaborate.



EDIT: strong_types is a namespace. It exists among other things of the alias create_strong_type:



namespace strong_type {
template <typename T, typename tag>
using create_strong_type = Strong_Type<T, tag>;

...
}

...

template <typename T, typename tag>
struct Strong_Type {
constexpr explicit Strong_Type(const T& value) : _value(value) {}
constexpr explicit Strong_Type(T&& value) : _value(std::move(value)) {}

constexpr T& operator()() noexcept { return _value; }

private:
T _value;
};









share|improve this question















I created a struct with two static functions for testing purposes. The first instance of f is called when an l-value reference is passed. The second instance is called when an r-value is passed:



template <typename _Tp>
struct T {
static constexpr void f(_Tp&) { std::cout << "f(T&) is called!n"; }
static constexpr void f(_Tp&&) { std::cout << "f(T&&) is called!n"; }
};


When I was experimenting with strong types, I found out the first instance, T::f(_Tp&) was called when I attempted to create the strong type implicitly. Why is this? (See following)



using T_int = T<int>;

T_int::f(
typename strong_types::create_strong_type<int, struct tag>(5)()
); // calls f::(T&) (?)

using KG = typename strong_types::create_strong_type<double, struct KG_tag>;
T_int::f(KG(4.2)()); // calls f(T&&)


Note that operator() returns the value given through the constructor.



Feel free to ask if I need to elaborate.



EDIT: strong_types is a namespace. It exists among other things of the alias create_strong_type:



namespace strong_type {
template <typename T, typename tag>
using create_strong_type = Strong_Type<T, tag>;

...
}

...

template <typename T, typename tag>
struct Strong_Type {
constexpr explicit Strong_Type(const T& value) : _value(value) {}
constexpr explicit Strong_Type(T&& value) : _value(std::move(value)) {}

constexpr T& operator()() noexcept { return _value; }

private:
T _value;
};






c++ reference c++14 lvalue type-alias






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 19 at 17:57

























asked Nov 19 at 16:57









Lourens Dijkstra

769




769








  • 3




    what is strong_types ?
    – Piotr Skotnicki
    Nov 19 at 17:32










  • Sure, but is it a third party library ?
    – Piotr Skotnicki
    Nov 19 at 17:40










  • Oo, I am sorry for my misunderstanding. strong_types is a namespace I created myself.
    – Lourens Dijkstra
    Nov 19 at 17:41






  • 1




    Also unrelated: Identifiers beginning with underscore, followed by uppercase letter are reserved and you are not allowed to use them.
    – user10605163
    Nov 19 at 17:45






  • 1




    Please fix the typos in your edits, the identifiers do not match, e.g. strong_type vs strong_types and Strong_Type and probably Strong_Type should be part of the namespace and before create_strong_type?. It doesn't compile the way it is even if generously moving around code.
    – user10605163
    Nov 19 at 17:51
















  • 3




    what is strong_types ?
    – Piotr Skotnicki
    Nov 19 at 17:32










  • Sure, but is it a third party library ?
    – Piotr Skotnicki
    Nov 19 at 17:40










  • Oo, I am sorry for my misunderstanding. strong_types is a namespace I created myself.
    – Lourens Dijkstra
    Nov 19 at 17:41






  • 1




    Also unrelated: Identifiers beginning with underscore, followed by uppercase letter are reserved and you are not allowed to use them.
    – user10605163
    Nov 19 at 17:45






  • 1




    Please fix the typos in your edits, the identifiers do not match, e.g. strong_type vs strong_types and Strong_Type and probably Strong_Type should be part of the namespace and before create_strong_type?. It doesn't compile the way it is even if generously moving around code.
    – user10605163
    Nov 19 at 17:51










3




3




what is strong_types ?
– Piotr Skotnicki
Nov 19 at 17:32




what is strong_types ?
– Piotr Skotnicki
Nov 19 at 17:32












Sure, but is it a third party library ?
– Piotr Skotnicki
Nov 19 at 17:40




Sure, but is it a third party library ?
– Piotr Skotnicki
Nov 19 at 17:40












Oo, I am sorry for my misunderstanding. strong_types is a namespace I created myself.
– Lourens Dijkstra
Nov 19 at 17:41




Oo, I am sorry for my misunderstanding. strong_types is a namespace I created myself.
– Lourens Dijkstra
Nov 19 at 17:41




1




1




Also unrelated: Identifiers beginning with underscore, followed by uppercase letter are reserved and you are not allowed to use them.
– user10605163
Nov 19 at 17:45




Also unrelated: Identifiers beginning with underscore, followed by uppercase letter are reserved and you are not allowed to use them.
– user10605163
Nov 19 at 17:45




1




1




Please fix the typos in your edits, the identifiers do not match, e.g. strong_type vs strong_types and Strong_Type and probably Strong_Type should be part of the namespace and before create_strong_type?. It doesn't compile the way it is even if generously moving around code.
– user10605163
Nov 19 at 17:51






Please fix the typos in your edits, the identifiers do not match, e.g. strong_type vs strong_types and Strong_Type and probably Strong_Type should be part of the namespace and before create_strong_type?. It doesn't compile the way it is even if generously moving around code.
– user10605163
Nov 19 at 17:51














1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










The difference is not due to using an alias (using), but to the type you pass as first template argument to create_strong_type. In one case, it's an int, and in the other, a double.



Try T<double>::f(KG(4.2)()); and you will see the argument is passed as lvalue reference (because of the return type of Strong_Type::operator(), which is T&).






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',
    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%2f53379373%2fwhy-does-type-aliasing-determine-whether-output-is-l-value-or-r-value%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








    up vote
    1
    down vote



    accepted










    The difference is not due to using an alias (using), but to the type you pass as first template argument to create_strong_type. In one case, it's an int, and in the other, a double.



    Try T<double>::f(KG(4.2)()); and you will see the argument is passed as lvalue reference (because of the return type of Strong_Type::operator(), which is T&).






    share|improve this answer

























      up vote
      1
      down vote



      accepted










      The difference is not due to using an alias (using), but to the type you pass as first template argument to create_strong_type. In one case, it's an int, and in the other, a double.



      Try T<double>::f(KG(4.2)()); and you will see the argument is passed as lvalue reference (because of the return type of Strong_Type::operator(), which is T&).






      share|improve this answer























        up vote
        1
        down vote



        accepted







        up vote
        1
        down vote



        accepted






        The difference is not due to using an alias (using), but to the type you pass as first template argument to create_strong_type. In one case, it's an int, and in the other, a double.



        Try T<double>::f(KG(4.2)()); and you will see the argument is passed as lvalue reference (because of the return type of Strong_Type::operator(), which is T&).






        share|improve this answer












        The difference is not due to using an alias (using), but to the type you pass as first template argument to create_strong_type. In one case, it's an int, and in the other, a double.



        Try T<double>::f(KG(4.2)()); and you will see the argument is passed as lvalue reference (because of the return type of Strong_Type::operator(), which is T&).







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 19 at 17:57









        Nelfeal

        4,170621




        4,170621






























            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.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • 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%2f53379373%2fwhy-does-type-aliasing-determine-whether-output-is-l-value-or-r-value%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

            "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

            Alcedinidae

            RAC Tourist Trophy