{"action":"created","issue":{"url":"https://api.github.com/repos/isocpp/CppCoreGuidelines/issues/526","repository_url":"https://api.github.com/repos/isocpp/CppCoreGuidelines","labels_url":"https://api.github.com/repos/isocpp/CppCoreGuidelines/issues/526/labels{/name}","comments_url":"https://api.github.com/repos/isocpp/CppCoreGuidelines/issues/526/comments","events_url":"https://api.github.com/repos/isocpp/CppCoreGuidelines/issues/526/events","html_url":"https://github.com/isocpp/CppCoreGuidelines/issues/526","id":133566453,"node_id":"MDU6SXNzdWUxMzM1NjY0NTM=","number":526,"title":"F.16 F.18 Consume and input parameters","user":{"login":"adarnon","id":5649771,"node_id":"MDQ6VXNlcjU2NDk3NzE=","avatar_url":"https://avatars3.githubusercontent.com/u/5649771?v=4","gravatar_id":"","url":"https://api.github.com/users/adarnon","html_url":"https://github.com/adarnon","followers_url":"https://api.github.com/users/adarnon/followers","following_url":"https://api.github.com/users/adarnon/following{/other_user}","gists_url":"https://api.github.com/users/adarnon/gists{/gist_id}","starred_url":"https://api.github.com/users/adarnon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adarnon/subscriptions","organizations_url":"https://api.github.com/users/adarnon/orgs","repos_url":"https://api.github.com/users/adarnon/repos","events_url":"https://api.github.com/users/adarnon/events{/privacy}","received_events_url":"https://api.github.com/users/adarnon/received_events","type":"User","site_admin":false},"labels":[{"id":261466357,"node_id":"MDU6TGFiZWwyNjE0NjYzNTc=","url":"https://api.github.com/repos/isocpp/CppCoreGuidelines/labels/open","name":"open","color":"5319e7","default":false}],"state":"open","locked":false,"assignee":{"login":"hsutter","id":1801526,"node_id":"MDQ6VXNlcjE4MDE1MjY=","avatar_url":"https://avatars1.githubusercontent.com/u/1801526?v=4","gravatar_id":"","url":"https://api.github.com/users/hsutter","html_url":"https://github.com/hsutter","followers_url":"https://api.github.com/users/hsutter/followers","following_url":"https://api.github.com/users/hsutter/following{/other_user}","gists_url":"https://api.github.com/users/hsutter/gists{/gist_id}","starred_url":"https://api.github.com/users/hsutter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hsutter/subscriptions","organizations_url":"https://api.github.com/users/hsutter/orgs","repos_url":"https://api.github.com/users/hsutter/repos","events_url":"https://api.github.com/users/hsutter/events{/privacy}","received_events_url":"https://api.github.com/users/hsutter/received_events","type":"User","site_admin":false},"assignees":[{"login":"hsutter","id":1801526,"node_id":"MDQ6VXNlcjE4MDE1MjY=","avatar_url":"https://avatars1.githubusercontent.com/u/1801526?v=4","gravatar_id":"","url":"https://api.github.com/users/hsutter","html_url":"https://github.com/hsutter","followers_url":"https://api.github.com/users/hsutter/followers","following_url":"https://api.github.com/users/hsutter/following{/other_user}","gists_url":"https://api.github.com/users/hsutter/gists{/gist_id}","starred_url":"https://api.github.com/users/hsutter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hsutter/subscriptions","organizations_url":"https://api.github.com/users/hsutter/orgs","repos_url":"https://api.github.com/users/hsutter/repos","events_url":"https://api.github.com/users/hsutter/events{/privacy}","received_events_url":"https://api.github.com/users/hsutter/received_events","type":"User","site_admin":false}],"milestone":null,"comments":7,"created_at":"2016-02-14T18:44:15Z","updated_at":"2018-12-14T09:32:10Z","closed_at":null,"author_association":"NONE","body":"Rule F.18 suggests you should always pass parameters by `X&&` and `std::move` them.\nHowever, in the case where you have a function that receives multiple parameters and it keeps a copy of all of them (a constructor, maybe), I believe the better way is to pass them by value and then `std::move` them. This also saves you the trouble of adding a Cartesian product of overloads with `const X&`.\n\nFor example:\n\n```\nclass Foo {\n    Foo(std::vector<int> a, std::vector<int> b): _a(std::move(a)), _b(std::move(b)) {}\nprivate:\n    std::vector<int> _a;\n    std::vector<int> _b;\n};\n```\n"},"comment":{"url":"https://api.github.com/repos/isocpp/CppCoreGuidelines/issues/comments/447268330","html_url":"https://github.com/isocpp/CppCoreGuidelines/issues/526#issuecomment-447268330","issue_url":"https://api.github.com/repos/isocpp/CppCoreGuidelines/issues/526","id":447268330,"node_id":"MDEyOklzc3VlQ29tbWVudDQ0NzI2ODMzMA==","user":{"login":"etam","id":220752,"node_id":"MDQ6VXNlcjIyMDc1Mg==","avatar_url":"https://avatars1.githubusercontent.com/u/220752?v=4","gravatar_id":"","url":"https://api.github.com/users/etam","html_url":"https://github.com/etam","followers_url":"https://api.github.com/users/etam/followers","following_url":"https://api.github.com/users/etam/following{/other_user}","gists_url":"https://api.github.com/users/etam/gists{/gist_id}","starred_url":"https://api.github.com/users/etam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/etam/subscriptions","organizations_url":"https://api.github.com/users/etam/orgs","repos_url":"https://api.github.com/users/etam/repos","events_url":"https://api.github.com/users/etam/events{/privacy}","received_events_url":"https://api.github.com/users/etam/received_events","type":"User","site_admin":false},"created_at":"2018-12-14T09:32:10Z","updated_at":"2018-12-14T09:32:10Z","author_association":"NONE","body":"It's been a while. Anything changed about detecting \"use after move\"?\r\n\r\nAnyway, I came here to give a comment about sinking arguments into a constructor.\r\n\r\nAs @adarnon wrote in the first comment, the consensus about writing constructors and avoiding overload explosion, is to take all arguments by value and move from them.\r\n\r\nI wanted to propose a different approach, that is a bit more explicit:\r\n\r\n```cpp\r\n// this function might become part of GSL or even standard\r\ntemplate <typename T>\r\nT copy(const T& obj)\r\n{\r\n    return obj;\r\n}\r\n\r\nclass Foo\r\n{\r\nprivate:\r\n    std::vector<int> m_v1, m_v2;\r\npublic:\r\n    // take arguments as rvalue refs, as all sink functions should\r\n    Foo(std::vector<int>&& v1, std::vector<int>&& v2)\r\n        : m_v1{std::move(v1)}\r\n        , m_v2{std::move(v2)}\r\n    {}\r\n};\r\n\r\nint main()\r\n{\r\n    { // move arguments, works as expected\r\n        auto v1 = std::vector<int>{1, 2, 3};\r\n        auto v2 = std::vector<int>{4, 5, 6};\r\n        auto foo = Foo{std::move(v1), std::move(v2)};\r\n    }\r\n    { // no move, fails to compile\r\n        auto v1 = std::vector<int>{1, 2, 3};\r\n        auto v2 = std::vector<int>{4, 5, 6};\r\n        auto foo = Foo{v1, v2};\r\n    }\r\n    { // you can't move const objects, fails to compile\r\n        const auto v1 = std::vector<int>{1, 2, 3};\r\n        const auto v2 = std::vector<int>{4, 5, 6};\r\n        auto foo = Foo{std::move(v1), std::move(v2)};\r\n    }\r\n    { // if you have object that cannot be moved, then copy it explicitly\r\n        const auto v1 = std::vector<int>{1, 2, 3};\r\n        const auto v2 = std::vector<int>{4, 5, 6};\r\n        auto foo = Foo{copy(v1), copy(v2)};\r\n    }\r\n}\r\n```"}}
{"actor":{"display_login":"etam"}}