Discussion:
[std-proposals] Extend an ADL search algorithm
Denis Kotov
2018-10-09 18:11:13 UTC
Permalink
Hello everyone,

I have prepared the proposal for extending an ADL search algorithm:

*Propousal for extension methods like.* Lets consider the following example:

namespace DeviceManager {
class Device {
public:
... // Other member functions
uint32_t getId() const {
return id_;
}
private:
... // Other member variables
uint32_t id_;
};

using DeviceList = std::vector<Device>;

Device mergeDeviceInfo(const Device & _first, const Device & _second)
{
... // Implementation
}
}

int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
DeviceManager::Device mergedDevice =
DeviceManager::mergeDeviceInfo(*foundDeviceIter0, *foundDeviceIter1);
... // Some other work
}
}

As you can see in case one helper function it is easy to manipulate and use
it, but in case of a lot of functions it would be better to support some
kind of extension methods:

namespace DeviceManager {
class Device {
public:
... // Other member functions
uint32_t getId() const {
return id_;
}
private:
... // Other member variables
uint32_t id_;
};

using DeviceList = std::vector<Device>;

// 1. If it is called by reference type prefer this overload function
Device mergeDeviceInfo(const Device & _first, const Device & _second)
{
... // Implementation
}
// 2. If it is called by pointer type prefer this overload function
Device mergeDeviceInfo(const Device * _firstPtr, const Device *
_secondPtr) {
... // Implementation
}
}

int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
// 1. Overload function for references if called
// ADL will search in dependent scopes also for calling functions
by object reference
DeviceManager::Device & firstFoundDevice = *foundDeviceIter0;
DeviceManager::Device & secondFoundDevice = *foundDeviceIter1;
DeviceManager::Device mergedDevice =
firstFoundDevice.mergeDeviceInfo(secondFoundDevice);

// 2. Overload function for pointers if called
// ADL will search in dependent scopes lso for calling functions by
object pointer
DeviceManager::Device mergedDevice =
foundDeviceIter0->mergeDeviceInfo(*foundDeviceIter1);
... // Some other work
}
}

*Propousal for extension of ADL on template parameter.* Lets consider the
following example:

namespace IPCBus {
class IClient {
public:
... // Other member functions
template <typename TClient>
static std::shared_ptr<IClient> buildClient() {
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE SKIPED
!!
return client;
}
protected:
Client() = default;
};
} // namespace IPCBus

class RealClient : public IClient {
public:
RealClient()
: IClient() {
}
};

using namespace std;

int main() {
auto realClient = make_shared<RealClient>();
// WE MISSED THE VERY IMPORTANT STEPS IN CREATION OF OBJECT !!
}

As you can see in case one helper function it is easy to manipulate and use
it, but in case of a lot of functions it would be better to support some
kind of extension methods:

namespace IPCBus {
class IClient {
public:
... // Other member functions
template <typename TClient>
static std::shared_ptr<IClient> buildClient() {
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE SKIPED
!!
return client;
}
protected:
Client() = default;
};

template <typename T, typename ... TArgs>
std::shared_ptr<T> make_shared(TArgs&&... _args) {
return IClient::buildClient(std::forward<TArgs>(_args)...);
}
} // namespace IPCBus

class RealClient : public IClient {
public:
RealClient()
: IClient() {
}
};

using namespace std;

int main() {
auto realClient = make_shared<RealClient>();
// We use our own version of make_shared that is delegate creation of
object to builder method
// Cool !!
}

As *Herb Sutter* said at *CppCon 2017: Herb Sutter “Meta: Thoughts on
generative C++”*:
"Abstraction are hiders by definition. If they did not do this they are
useless ..."
"It's not the problem. It is the point."

I see this suggestion to extend *ADL* search on caller object and on
template parameter as simplifier for Library Writters and also General
Programmers
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/799e13cb-4354-4ffe-8568-276e1cbfe61c%40isocpp.org.
Denis Kotov
2018-10-09 18:16:50 UTC
Permalink
This proposal is available on GitHub also
https://github.com/redradist/cpp_standard_propousals/blob/master/ADL%20Extension.html
Post by Denis Kotov
Hello everyone,
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
DeviceManager::Device mergedDevice =
DeviceManager::mergeDeviceInfo(*foundDeviceIter0, *foundDeviceIter1);
... // Some other work
}
}
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
// 1. If it is called by reference type prefer this overload function
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
// 2. If it is called by pointer type prefer this overload function
Device mergeDeviceInfo(const Device * _firstPtr, const Device *
_secondPtr) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
// 1. Overload function for references if called
// ADL will search in dependent scopes also for calling functions
by object reference
DeviceManager::Device & firstFoundDevice = *foundDeviceIter0;
DeviceManager::Device & secondFoundDevice = *foundDeviceIter1;
DeviceManager::Device mergedDevice =
firstFoundDevice.mergeDeviceInfo(secondFoundDevice);
// 2. Overload function for pointers if called
// ADL will search in dependent scopes lso for calling functions
by object pointer
DeviceManager::Device mergedDevice =
foundDeviceIter0->mergeDeviceInfo(*foundDeviceIter1);
... // Some other work
}
}
*Propousal for extension of ADL on template parameter.* Lets consider the
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE SKIPED
!!
return client;
}
Client() = default;
};
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// WE MISSED THE VERY IMPORTANT STEPS IN CREATION OF OBJECT !!
}
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE SKIPED
!!
return client;
}
Client() = default;
};
}
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// We use our own version of make_shared that is delegate creation
of object to builder method
// Cool !!
}
As *Herb Sutter* said at *CppCon 2017: Herb Sutter “Meta: Thoughts on
"Abstraction are hiders by definition. If they did not do this they are
useless ..."
"It's not the problem. It is the point."
I see this suggestion to extend *ADL* search on caller object and on
template parameter as simplifier for Library Writters and also General
Programmers
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cf51a959-42d4-42c5-9e25-1455681402ff%40isocpp.org.
Gašper Ažman
2018-10-09 20:31:12 UTC
Permalink
Hi Denis,

You might want to include a link to a rendered version of the HTML on your
github. I would also suggest using bikeshed (
https://github.com/tabatkins/bikeshed ) to write it, as you will get
automatic code highlighting and help with specifying the various needed
sections. This will make it easier for everyone to read your proposal.

As an example, here is a published one:
https://atomgalaxy.github.io/brevzin-wg21/0847_deducing_this/p0847r1.html
The source is here (enable github sites to get it to display properly):
https://github.com/atomgalaxy/brevzin-wg21/tree/master/0847_deducing_this

Everyone will thank you :).

Gašper
Post by Denis Kotov
This proposal is available on GitHub also
https://github.com/redradist/cpp_standard_propousals/blob/master/ADL%20Extension.html
втПрМОк, 9 Пктября 2018 г., 21:11:13 UTC+3 пПльзПватель Denis Kotov
Post by Denis Kotov
Hello everyone,
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
DeviceManager::Device mergedDevice =
DeviceManager::mergeDeviceInfo(*foundDeviceIter0, *foundDeviceIter1);
... // Some other work
}
}
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
// 1. If it is called by reference type prefer this overload function
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
// 2. If it is called by pointer type prefer this overload function
Device mergeDeviceInfo(const Device * _firstPtr, const Device *
_secondPtr) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
// 1. Overload function for references if called
// ADL will search in dependent scopes also for calling functions
by object reference
DeviceManager::Device & firstFoundDevice = *foundDeviceIter0;
DeviceManager::Device & secondFoundDevice = *foundDeviceIter1;
DeviceManager::Device mergedDevice =
firstFoundDevice.mergeDeviceInfo(secondFoundDevice);
// 2. Overload function for pointers if called
// ADL will search in dependent scopes lso for calling functions
by object pointer
DeviceManager::Device mergedDevice =
foundDeviceIter0->mergeDeviceInfo(*foundDeviceIter1);
... // Some other work
}
}
*Propousal for extension of ADL on template parameter.* Lets consider
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE
SKIPED !!
return client;
}
Client() = default;
};
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// WE MISSED THE VERY IMPORTANT STEPS IN CREATION OF OBJECT !!
}
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE
SKIPED !!
return client;
}
Client() = default;
};
}
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// We use our own version of make_shared that is delegate creation
of object to builder method
// Cool !!
}
As *Herb Sutter* said at *CppCon 2017: Herb Sutter “Meta: Thoughts on
"Abstraction are hiders by definition. If they did not do this they are
useless ..."
"It's not the problem. It is the point."
I see this suggestion to extend *ADL* search on caller object and on
template parameter as simplifier for Library Writters and also General
Programmers
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cf51a959-42d4-42c5-9e25-1455681402ff%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cf51a959-42d4-42c5-9e25-1455681402ff%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAANG%3DkXQq2jmmDmrbmTe19hhF4Ya8QXX-a7amEz4kiZEadD7cQ%40mail.gmail.com.
Denis Kotov
2018-10-10 15:10:13 UTC
Permalink
Thank you Gašper,

I will use it

втПрМОк, 9 Пктября 2018 г., 23:31:26 UTC+3 пПльзПватель GaÅ¡per AÅŸman
Post by Gašper Ažman
Hi Denis,
You might want to include a link to a rendered version of the HTML on your
github. I would also suggest using bikeshed (
https://github.com/tabatkins/bikeshed ) to write it, as you will get
automatic code highlighting and help with specifying the various needed
sections. This will make it easier for everyone to read your proposal.
https://atomgalaxy.github.io/brevzin-wg21/0847_deducing_this/p0847r1.html
https://github.com/atomgalaxy/brevzin-wg21/tree/master/0847_deducing_this
Everyone will thank you :).
Gašper
Post by Denis Kotov
This proposal is available on GitHub also
https://github.com/redradist/cpp_standard_propousals/blob/master/ADL%20Extension.html
втПрМОк, 9 Пктября 2018 г., 21:11:13 UTC+3 пПльзПватель Denis Kotov
Post by Denis Kotov
Hello everyone,
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
DeviceManager::Device mergedDevice =
DeviceManager::mergeDeviceInfo(*foundDeviceIter0, *foundDeviceIter1);
... // Some other work
}
}
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
// 1. If it is called by reference type prefer this overload function
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
// 2. If it is called by pointer type prefer this overload function
Device mergeDeviceInfo(const Device * _firstPtr, const Device *
_secondPtr) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
// 1. Overload function for references if called
// ADL will search in dependent scopes also for calling
functions by object reference
DeviceManager::Device & firstFoundDevice = *foundDeviceIter0;
DeviceManager::Device & secondFoundDevice = *foundDeviceIter1;
DeviceManager::Device mergedDevice =
firstFoundDevice.mergeDeviceInfo(secondFoundDevice);
// 2. Overload function for pointers if called
// ADL will search in dependent scopes lso for calling functions
by object pointer
DeviceManager::Device mergedDevice =
foundDeviceIter0->mergeDeviceInfo(*foundDeviceIter1);
... // Some other work
}
}
*Propousal for extension of ADL on template parameter.* Lets consider
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE
SKIPED !!
return client;
}
Client() = default;
};
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// WE MISSED THE VERY IMPORTANT STEPS IN CREATION OF OBJECT !!
}
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE
SKIPED !!
return client;
}
Client() = default;
};
}
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// We use our own version of make_shared that is delegate creation
of object to builder method
// Cool !!
}
As *Herb Sutter* said at *CppCon 2017: Herb Sutter “Meta: Thoughts on
"Abstraction are hiders by definition. If they did not do this they are
useless ..."
"It's not the problem. It is the point."
I see this suggestion to extend *ADL* search on caller object and on
template parameter as simplifier for Library Writters and also General
Programmers
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cf51a959-42d4-42c5-9e25-1455681402ff%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cf51a959-42d4-42c5-9e25-1455681402ff%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4782ecca-e1e8-4c0d-bc5b-7d769fb79387%40isocpp.org.
Richard Smith
2018-10-09 20:28:24 UTC
Permalink
Post by Denis Kotov
Hello everyone,
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
DeviceManager::Device mergedDevice =
DeviceManager::mergeDeviceInfo(*foundDeviceIter0, *foundDeviceIter1);
... // Some other work
}
}
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
// 1. If it is called by reference type prefer this overload function
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
// 2. If it is called by pointer type prefer this overload function
Device mergeDeviceInfo(const Device * _firstPtr, const Device *
_secondPtr) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
// 1. Overload function for references if called
// ADL will search in dependent scopes also for calling functions
by object reference
DeviceManager::Device & firstFoundDevice = *foundDeviceIter0;
DeviceManager::Device & secondFoundDevice = *foundDeviceIter1;
DeviceManager::Device mergedDevice =
firstFoundDevice.mergeDeviceInfo(secondFoundDevice);
// 2. Overload function for pointers if called
// ADL will search in dependent scopes lso for calling functions
by object pointer
DeviceManager::Device mergedDevice =
foundDeviceIter0->mergeDeviceInfo(*foundDeviceIter1);
... // Some other work
}
}
*Propousal for extension of ADL on template parameter.* Lets consider the
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE SKIPED
!!
return client;
}
Client() = default;
};
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// WE MISSED THE VERY IMPORTANT STEPS IN CREATION OF OBJECT !!
If you don't want RealClient instances to be created by calling the default
constructor, the default constructor should not be public. There are other
techniques you can use to allow IClient to create instances of RealClient
without exposing a public default constructor that creates a broken object.
Your approach doesn't stop someone from doing this:

make_unique<RealClient>() // still broken

or this:

std::make_shared<RealClient>() // still broken

It's also broken by the intent of P0551R3 (adopted for C++20), which
intends to make it possible to implement standard library functions as
function objects instead of as real functions, and by P0921R2, which says
that you can't rely on (for instance) how a standard-library function will
partially order with respect to a function of your own.

So I don't think this approach really solves the problem you're trying to
address, especially not when used to subvert calls to standard library
functions.

}
Post by Denis Kotov
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE SKIPED
!!
return client;
}
Client() = default;
};
}
This, if in scope, would likely be ambiguous with std::make_shared. And if
you make it a better overload candidate, it would hijack all make_shared
calls that should invoke std::make_shared. Adding an overload to someone
else's overload set, when they didn't design for their overload set to be
extensible, is a very bad design practice.
Post by Denis Kotov
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// We use our own version of make_shared that is delegate creation
of object to builder method
// Cool !!
}
As *Herb Sutter* said at *CppCon 2017: Herb Sutter “Meta: Thoughts on
"Abstraction are hiders by definition. If they did not do this they are
useless ..."
"It's not the problem. It is the point."
I see this suggestion to extend *ADL* search on caller object and on
template parameter as simplifier for Library Writters and also General
Programmers
I don't agree at all with your motivation, but nonetheless I do agree with
your conclusion: it does seem reasonable for ADL to consider associated
classes and namespaces of template arguments in the case where the function
name is a template-id. I suspect this was not done previously because the
callee in a function call for which ADL is performed was very rarely a
template-id prior to P0846R0, but now we've adopted that paper for C++20,
it would make sense to take the associated classes and namespaces of the
template arguments into account, and especially because we now allow
objects of class type as non-type template arguments:

namespace N {
struct Params { /*...*/ };
auto make_dynamic(Params P) { /*...*/ }
template<Params P> auto make_static() { /*...*/ }
}
auto x = make_dynamic(N::Params{1, 2, 3}); // OK
auto y = make_static<N::Params{1, 2, 3}>(); // error today, could be valid
tomorrow
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOfiQqm-U3tn%3DyC2ZRnacJbq2hx4bq1p7Da7HpCO4ZD3Ye_%3DnA%40mail.gmail.com.
Denis Kotov
2018-10-10 07:11:53 UTC
Permalink
Hello Richard,

With make_shared it was just an example, but nonetheless I wanted to make
*ADL* look-up on template parameter dependent scope just for more
flexibility for developer
I appreciate that you like the idea for searching on template parameter

What about my* first proposal* ? About extension methods:

namespace DeviceManager {
class Device {
public:
... // Other member functions
uint32_t getId() const {
return id_;
}
private:
... // Other member variables
uint32_t id_;
};

using DeviceList = std::vector<Device>;

// 1. If it is called by reference type prefer this overload function
Device mergeDeviceInfo(const Device & _first, const Device & _second)
{
... // Implementation
}
// 2. If it is called by pointer type prefer this overload function
Device mergeDeviceInfo(const Device * _firstPtr, const Device *
_secondPtr) {
... // Implementation
}
}

int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto founFirstDeviceIter = std::find_if(deviceList.begin(
), deviceList.end(), [=] {
... // Some first creteria
});
auto foundSecondDeviceIter = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {

DeviceManager::Device & firstFoundDevice = *founFirstDeviceIter;
DeviceManager::Device & secondFoundDevice = *foundSecondDeviceIter;


*// Extension method example 1: Overload function for references if
called // ADL will search in dependent scopes also for calling
functions by object reference*
DeviceManager::Device mergedDevice =* firstFoundDevice.*
*mergeDeviceInfo(**secondFoundDevice); **// Extension method instead of *
*DeviceManager::**mergeDeviceInfo(**firstFoundDevice**,** secondFoundDevice*
*)*


*// Extension method example 2: Overload function for pointers if
called // ADL will search in dependent scopes lso for calling
functions by object pointer*
DeviceManager::Device mergedDevice = *founFirstDeviceIter->*
*mergeDeviceInfo(***foundDeviceIter1); // **Extension method instead of *
*DeviceManager::**mergeDeviceInfo(**founFirstDeviceIter, **foundDeviceIter1*
*)*

... // Some other work
}
}

What do you think ?

втПрМОк, 9 Пктября 2018 г., 23:28:42 UTC+3 пПльзПватель Richard Smith
Post by Richard Smith
Post by Denis Kotov
Hello everyone,
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
DeviceManager::Device mergedDevice =
DeviceManager::mergeDeviceInfo(*foundDeviceIter0, *foundDeviceIter1);
... // Some other work
}
}
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
// 1. If it is called by reference type prefer this overload function
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
// 2. If it is called by pointer type prefer this overload function
Device mergeDeviceInfo(const Device * _firstPtr, const Device *
_secondPtr) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
// 1. Overload function for references if called
// ADL will search in dependent scopes also for calling functions
by object reference
DeviceManager::Device & firstFoundDevice = *foundDeviceIter0;
DeviceManager::Device & secondFoundDevice = *foundDeviceIter1;
DeviceManager::Device mergedDevice =
firstFoundDevice.mergeDeviceInfo(secondFoundDevice);
// 2. Overload function for pointers if called
// ADL will search in dependent scopes lso for calling functions
by object pointer
DeviceManager::Device mergedDevice =
foundDeviceIter0->mergeDeviceInfo(*foundDeviceIter1);
... // Some other work
}
}
*Propousal for extension of ADL on template parameter.* Lets consider
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE
SKIPED !!
return client;
}
Client() = default;
};
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// WE MISSED THE VERY IMPORTANT STEPS IN CREATION OF OBJECT !!
If you don't want RealClient instances to be created by calling the
default constructor, the default constructor should not be public. There
are other techniques you can use to allow IClient to create instances of
RealClient without exposing a public default constructor that creates a
make_unique<RealClient>() // still broken
std::make_shared<RealClient>() // still broken
It's also broken by the intent of P0551R3 (adopted for C++20), which
intends to make it possible to implement standard library functions as
function objects instead of as real functions, and by P0921R2, which says
that you can't rely on (for instance) how a standard-library function will
partially order with respect to a function of your own.
So I don't think this approach really solves the problem you're trying to
address, especially not when used to subvert calls to standard library
functions.
}
Post by Denis Kotov
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE
SKIPED !!
return client;
}
Client() = default;
};
}
This, if in scope, would likely be ambiguous with std::make_shared. And if
you make it a better overload candidate, it would hijack all make_shared
calls that should invoke std::make_shared. Adding an overload to someone
else's overload set, when they didn't design for their overload set to be
extensible, is a very bad design practice.
Post by Denis Kotov
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// We use our own version of make_shared that is delegate creation
of object to builder method
// Cool !!
}
As *Herb Sutter* said at *CppCon 2017: Herb Sutter “Meta: Thoughts on
"Abstraction are hiders by definition. If they did not do this they are
useless ..."
"It's not the problem. It is the point."
I see this suggestion to extend *ADL* search on caller object and on
template parameter as simplifier for Library Writters and also General
Programmers
I don't agree at all with your motivation, but nonetheless I do agree with
your conclusion: it does seem reasonable for ADL to consider associated
classes and namespaces of template arguments in the case where the function
name is a template-id. I suspect this was not done previously because the
callee in a function call for which ADL is performed was very rarely a
template-id prior to P0846R0, but now we've adopted that paper for C++20,
it would make sense to take the associated classes and namespaces of the
template arguments into account, and especially because we now allow
namespace N {
struct Params { /*...*/ };
auto make_dynamic(Params P) { /*...*/ }
template<Params P> auto make_static() { /*...*/ }
}
auto x = make_dynamic(N::Params{1, 2, 3}); // OK
auto y = make_static<N::Params{1, 2, 3}>(); // error today, could be valid
tomorrow
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9579b759-d5c0-41c9-a224-5c54fcf88274%40isocpp.org.
Richard Smith
2018-10-10 20:40:01 UTC
Permalink
Post by Denis Kotov
Hello Richard,
With make_shared it was just an example, but nonetheless I wanted to make
*ADL* look-up on template parameter dependent scope just for more
flexibility for developer
I appreciate that you like the idea for searching on template parameter
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
using DeviceList = std::vector<Device>;
// 1. If it is called by reference type prefer this overload function
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
// 2. If it is called by pointer type prefer this overload function
Device mergeDeviceInfo(const Device * _firstPtr, const Device *
_secondPtr) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto founFirstDeviceIter = std::find_if(deviceList.begin(
), deviceList.end(), [=] {
... // Some first creteria
});
auto foundSecondDeviceIter = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
DeviceManager::Device & firstFoundDevice = *founFirstDeviceIter;
DeviceManager::Device & secondFoundDevice = *foundSecondDeviceIter;
*// Extension method example 1: Overload function for references if
called // ADL will search in dependent scopes also for calling
functions by object reference*
DeviceManager::Device mergedDevice =* firstFoundDevice.*
*mergeDeviceInfo(**secondFoundDevice); **// Extension method instead of *
*DeviceManager::**mergeDeviceInfo(**firstFoundDevice**,**
secondFoundDevice**)*
*// Extension method example 2: Overload function for pointers if
called // ADL will search in dependent scopes lso for calling
functions by object pointer*
DeviceManager::Device mergedDevice = *founFirstDeviceIter->*
*mergeDeviceInfo(***foundDeviceIter1); // **Extension method instead of *
*DeviceManager::**mergeDeviceInfo(**founFirstDeviceIter, *
*foundDeviceIter1**)*
... // Some other work
}
}
What do you think ?
Something very similar to this has already been proposed as part of unified
function call syntax (n4474), and the C++ committee rejected it. I don't
think it will be reconsidered unless you have substantial new arguments /
evidence for it, or a new design that avoids the problems with the previous
approach.
Post by Denis Kotov
втПрМОк, 9 Пктября 2018 г., 23:28:42 UTC+3 пПльзПватель Richard Smith
Post by Richard Smith
Post by Denis Kotov
Hello everyone,
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
DeviceManager::Device mergedDevice =
DeviceManager::mergeDeviceInfo(*foundDeviceIter0, *foundDeviceIter1);
... // Some other work
}
}
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace DeviceManager {
class Device {
... // Other member functions
uint32_t getId() const {
return id_;
}
... // Other member variables
uint32_t id_;
};
// 1. If it is called by reference type prefer this overload function
Device mergeDeviceInfo(const Device & _first, const Device &
_second) {
... // Implementation
}
// 2. If it is called by pointer type prefer this overload function
Device mergeDeviceInfo(const Device * _firstPtr, const Device *
_secondPtr) {
... // Implementation
}
}
int main() {
DeviceManager::DeviceList deviceList;
... // Some work
auto foundDeviceIter0 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some first creteria
});
auto foundDeviceIter1 = std::find_if(deviceList.begin(),
deviceList.end(), [=] {
... // Some second creteria
});
if (deviceList.end() != foundDeviceIter0 && deviceList.end() !=
foundDeviceIter1) {
// 1. Overload function for references if called
// ADL will search in dependent scopes also for calling
functions by object reference
DeviceManager::Device & firstFoundDevice = *foundDeviceIter0;
DeviceManager::Device & secondFoundDevice = *foundDeviceIter1;
DeviceManager::Device mergedDevice =
firstFoundDevice.mergeDeviceInfo(secondFoundDevice);
// 2. Overload function for pointers if called
// ADL will search in dependent scopes lso for calling functions
by object pointer
DeviceManager::Device mergedDevice =
foundDeviceIter0->mergeDeviceInfo(*foundDeviceIter1);
... // Some other work
}
}
*Propousal for extension of ADL on template parameter.* Lets consider
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE
SKIPED !!
return client;
}
Client() = default;
};
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// WE MISSED THE VERY IMPORTANT STEPS IN CREATION OF OBJECT !!
If you don't want RealClient instances to be created by calling the
default constructor, the default constructor should not be public. There
are other techniques you can use to allow IClient to create instances of
RealClient without exposing a public default constructor that creates a
make_unique<RealClient>() // still broken
std::make_shared<RealClient>() // still broken
It's also broken by the intent of P0551R3 (adopted for C++20), which
intends to make it possible to implement standard library functions as
function objects instead of as real functions, and by P0921R2, which says
that you can't rely on (for instance) how a standard-library function will
partially order with respect to a function of your own.
So I don't think this approach really solves the problem you're trying to
address, especially not when used to subvert calls to standard library
functions.
}
Post by Denis Kotov
As you can see in case one helper function it is easy to manipulate and
use it, but in case of a lot of functions it would be better to support
namespace IPCBus {
class IClient {
... // Other member functions
auto client = std::shared_ptr(new TClient);
... // IMPORTANT THINGS AFTER INITIALIZATION. CANNOT BE
SKIPED !!
return client;
}
Client() = default;
};
}
This, if in scope, would likely be ambiguous with std::make_shared. And
if you make it a better overload candidate, it would hijack all make_shared
calls that should invoke std::make_shared. Adding an overload to someone
else's overload set, when they didn't design for their overload set to be
extensible, is a very bad design practice.
Post by Denis Kotov
} // namespace IPCBus
class RealClient : public IClient {
RealClient()
: IClient() {
}
};
using namespace std;
int main() {
// We use our own version of make_shared that is delegate creation
of object to builder method
// Cool !!
}
As *Herb Sutter* said at *CppCon 2017: Herb Sutter “Meta: Thoughts on
"Abstraction are hiders by definition. If they did not do this they are
useless ..."
"It's not the problem. It is the point."
I see this suggestion to extend *ADL* search on caller object and on
template parameter as simplifier for Library Writters and also General
Programmers
I don't agree at all with your motivation, but nonetheless I do agree
with your conclusion: it does seem reasonable for ADL to consider
associated classes and namespaces of template arguments in the case where
the function name is a template-id. I suspect this was not done previously
because the callee in a function call for which ADL is performed was very
rarely a template-id prior to P0846R0, but now we've adopted that paper for
C++20, it would make sense to take the associated classes and namespaces of
the template arguments into account, and especially because we now allow
namespace N {
struct Params { /*...*/ };
auto make_dynamic(Params P) { /*...*/ }
template<Params P> auto make_static() { /*...*/ }
}
auto x = make_dynamic(N::Params{1, 2, 3}); // OK
auto y = make_static<N::Params{1, 2, 3}>(); // error today, could be
valid tomorrow
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9579b759-d5c0-41c9-a224-5c54fcf88274%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9579b759-d5c0-41c9-a224-5c54fcf88274%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOfiQqmM44LZXC28U4A%3Dn2PV9TJCDYPf9NRaUaYX4XGEXDv0Tg%40mail.gmail.com.
Loading...