[qvm] deduce_xx traits wouldn't introduce ODR issues.
Hi, I wonder if the deduce_xx traits wouldn't introduce ODR issues. Remember the TBoost.Conversion library where conversion between two types was customizable. The fact that deduce_xx traits have two types would promote ODR as there is no one type that is expected to do the customization. I believe that changing the default to something depending on the first argument will be better than using the specific qvm type as result. If this is not enough, you could add symbolic operations taken the result type as parameter, e.g. if a+b is not something specified by A, the user could use sum<C>(a,b) Forget my comment if there is no ODR issue. Best, Vicente
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Hi,
I wonder if the deduce_xx traits wouldn't introduce ODR issues. Remember the TBoost.Conversion library where conversion between two types was customizable. The fact that deduce_xx traits have two types would promote ODR as there is no one type that is expected to do the customization.
I believe that changing the default to something depending on the first argument will be better than using the specific qvm type as result.
If I understand your concern correctly, you're saying that if one type defines a deduce_m2 specialization, it might clash with specializations defined by other types. That isn't possible because deduce_m2 is always specialized for *two* (different) types. For example, two different matrix types (say, Mat44 and float44) would not "know" about each other; the programmer who needs to bring the two types together into the same program (and wants to be able to multiply a Mat44 by a float44) could specialize deduce_m2 to specify what type of matrix he wants (by default he'll get a suitable instantiation of the qvm::mat template.) Emil
Le 10/12/2015 00:15, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Hi,
I wonder if the deduce_xx traits wouldn't introduce ODR issues. Remember the TBoost.Conversion library where conversion between two types was customizable. The fact that deduce_xx traits have two types would promote ODR as there is no one type that is expected to do the customization.
I believe that changing the default to something depending on the first argument will be better than using the specific qvm type as result.
If I understand your concern correctly, you're saying that if one type defines a deduce_m2 specialization, it might clash with specializations defined by other types. That isn't possible because deduce_m2 is always specialized for *two* (different) types.
For example, two different matrix types (say, Mat44 and float44) would not "know" about each other; the programmer who needs to bring the two types together into the same program (and wants to be able to multiply a Mat44 by a float44) could specialize deduce_m2 to specify what type of matrix he wants (by default he'll get a suitable instantiation of the qvm::mat template.)
The problem appear when two such programmers do it (think of 3pp). Vicente
On Wed, Dec 9, 2015 at 10:36 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:15, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
The problem appear when two such programmers do it (think of 3pp).
If within one program two programmers introduce two different definitions under the same name, yes you have ODR but that is hardly a library problem. :)
Emil
Le 10/12/2015 08:30, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 10:36 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:15, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
The problem appear when two such programmers do it (think of 3pp).
If within one program two programmers introduce two different definitions under the same name, yes you have ODR but that is hardly a library problem. :)
Hmm. This is a library issue, because the library provides an interface that allows to configure types that don't know each other by two different parts. TBoost.Conversion was rejected exactly by this reason. Vicente
Vicente J. Botet Escriba wrote:
Le 10/12/2015 08:30, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 10:36 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:15, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
The problem appear when two such programmers do it (think of 3pp).
If within one program two programmers introduce two different definitions under the same name, yes you have ODR but that is hardly a library problem. :)
Hmm. This is a library issue, because the library provides an interface that allows to configure types that don't know each other by two different parts.
TBoost.Conversion was rejected exactly by this reason.
This indeed is an important point, unfortunately I cannot take it into account because it wasn't mentioned in any review. Vincente, do you plan to write one? Regards, Adam
On Wed, Dec 23, 2015 at 6:24 AM, Adam Wulkiewicz
Vicente J. Botet Escriba wrote:
Le 10/12/2015 08:30, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 10:36 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:15, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:
The problem appear when two such programmers do it (think of 3pp).
If within one program two programmers introduce two different definitions
under the same name, yes you have ODR but that is hardly a library problem. :)
Hmm. This is a library issue, because the library provides an interface that allows to configure types that don't know each other by two different parts.
TBoost.Conversion was rejected exactly by this reason.
This indeed is an important point, unfortunately I cannot take it into account because it wasn't mentioned in any review. Vincente, do you plan to write one?
If the problem is that QVM allows you to specialize a type template, and that it is possible for two programmers to introduce two different definitions for the same specialization, how is that a library issue? If that's a problem then we can't allow any templates in any library interface, which seems odd. Emil
Emil Dotchevski wrote:
On Wed, Dec 23, 2015 at 6:24 AM, Adam Wulkiewicz
wrote: Vicente J. Botet Escriba wrote:
Le 10/12/2015 08:30, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 10:36 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:15, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:
The problem appear when two such programmers do it (think of 3pp). If within one program two programmers introduce two different definitions
under the same name, yes you have ODR but that is hardly a library problem. :)
Hmm. This is a library issue, because the library provides an interface that allows to configure types that don't know each other by two different parts.
TBoost.Conversion was rejected exactly by this reason.
This indeed is an important point, unfortunately I cannot take it into account because it wasn't mentioned in any review. Vincente, do you plan to write one?
If the problem is that QVM allows you to specialize a type template, and that it is possible for two programmers to introduce two different definitions for the same specialization, how is that a library issue? If that's a problem then we can't allow any templates in any library interface, which seems odd.
Basically I think we should clarify this. AFAIU the problem might occur if there were e.g. two libraries (abc and def) providing their own matrix representations (e.g. abc::mat4x4 and def::mat4x4). Then we'd have two other libraries (X and Y) both using those two matrix types together with QVM. So both X and Y libraries would have to specialize QVM traits for abc::mat4x4 and def::mat4x4. Then, if both X and Y libraries were included in a program there would be problems since the specializations of QVM traits would be duplicated. I'm not sure if we could do anything about it because similar problem would occur every time when any traits was required by any library. So AFAIU this is what Emil is saying. Or are deduce_xx traits somehow different than other QVM traits? Vincente is this what you had in mind or was it a different issue? Regards, Adam
On Wed, Dec 23, 2015 at 2:44 PM, Adam Wulkiewicz
Emil Dotchevski wrote:
On Wed, Dec 23, 2015 at 6:24 AM, Adam Wulkiewicz < adam.wulkiewicz@gmail.com> wrote:
Vicente J. Botet Escriba wrote:
Le 10/12/2015 08:30, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 10:36 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:15, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba <
> vicente.botet@wanadoo.fr> wrote: > > The problem appear when two such programmers do it (think of 3pp). > If within one program two programmers introduce two different definitions
under the same name, yes you have ODR but that is hardly a library problem. :)
Hmm. This is a library issue, because the library provides an interface
that allows to configure types that don't know each other by two different parts.
TBoost.Conversion was rejected exactly by this reason.
This indeed is an important point, unfortunately I cannot take it into
account because it wasn't mentioned in any review. Vincente, do you plan to write one?
If the problem is that QVM allows you to specialize a type template, and
that it is possible for two programmers to introduce two different definitions for the same specialization, how is that a library issue? If that's a problem then we can't allow any templates in any library interface, which seems odd.
Basically I think we should clarify this. AFAIU the problem might occur if there were e.g. two libraries (abc and def) providing their own matrix representations (e.g. abc::mat4x4 and def::mat4x4). Then we'd have two other libraries (X and Y) both using those two matrix types together with QVM. So both X and Y libraries would have to specialize QVM traits for abc::mat4x4 and def::mat4x4.
They don't *have* to, the deduce_m2 template does have a default definition.
Then, if both X and Y libraries were included in a program there would be problems since the specializations of QVM traits would be duplicated.
Yes, however that is true for any specialization of any template any library defines. It makes no sense to say that there is a problem with a library because the *user* might violate ODR. Emil
2015-12-24 0:10 GMT+01:00 Emil Dotchevski
On Wed, Dec 23, 2015 at 2:44 PM, Adam Wulkiewicz < adam.wulkiewicz@gmail.com> wrote:
Basically I think we should clarify this. AFAIU the problem might occur if there were e.g. two libraries (abc and def) providing their own matrix representations (e.g. abc::mat4x4 and def::mat4x4). Then we'd have two other libraries (X and Y) both using those two matrix types together with QVM. So both X and Y libraries would have to specialize QVM traits for abc::mat4x4 and def::mat4x4.
They don't *have* to, the deduce_m2 template does have a default definition.
Then, if both X and Y libraries were included in a program there would be problems since the specializations of QVM traits would be duplicated.
Yes, however that is true for any specialization of any template any library defines. It makes no sense to say that there is a problem with a library because the *user* might violate ODR.
Yes, this is my understanding. I'd simply like to hear from Vicente if this is the case he had in mind or something else that I possibly cannot see. Adam
On December 25, 2015 1:38:36 AM EST, Adam Wulkiewicz
I think we should clarify this. AFAIU the problem might occur if there were e.g. two libraries (abc and def) providing their own matrix representations (e.g. abc::mat4x4 and def::mat4x4). Then we'd have two other libraries (X and Y) both using those two matrix types together with QVM. So both X and Y libraries would have to specialize QVM traits for abc::mat4x4 and def::mat4x4.
[snip] I think, rather than X and Y providing conflicting definitions, the problem is that abc provides a specialization to allow interoperability with def, and def does the same for abc. Using the two libraries, in that case, always creates a conflict. ___ Rob (Sent from my portable computation engine)
On 25.12.2015 13:03, Rob Stewart wrote:
I think, rather than X and Y providing conflicting definitions, the problem is that abc provides a specialization to allow interoperability with def, and def does the same for abc. Using the two libraries, in that case, always creates a conflict.
This implies a circular dependency between abc and def. If those libraries are that tightly coupled, surely they can work out this conflict between themselves? -- Rainer Deyke (rainerd@eldwood.com)
On December 26, 2015 4:54:19 AM EST, Rainer Deyke
On 25.12.2015 13:03, Rob Stewart wrote:
I think, rather than X and Y providing conflicting definitions, the problem is that abc provides a specialization to allow interoperability with def, and def does the same for abc. Using the two libraries, in that case, always creates a conflict.
This implies a circular dependency between abc and def. If those libraries are that tightly coupled, surely they can work out this conflict between themselves?
It implies no such thing. It implies that each library provider chose, independently, to offer interoperability with the other using QVM. ___ Rob (Sent from my portable computation engine)
On Sat, Dec 26, 2015 at 5:19 PM, Rob Stewart
On December 26, 2015 4:54:19 AM EST, Rainer Deyke
wrote: On 25.12.2015 13:03, Rob Stewart wrote:
I think, rather than X and Y providing conflicting definitions, the problem is that abc provides a specialization to allow interoperability with def, and def does the same for abc. Using the two libraries, in that case, always creates a conflict.
This implies a circular dependency between abc and def. If those libraries are that tightly coupled, surely they can work out this conflict between themselves?
It implies no such thing. It implies that each library provider chose, independently, to offer interoperability with the other using QVM.
It isn't exactly interoperability. The specialization in question isn't needed to make library X and Y compatible with each other using QVM, that's automatic. It only specifies the return type of operator* when multiplying e.g. X::matrix by Y::matrix; and it is plain wrong for X or Y to specify that, because the user most likely wants to get a my_matrix instead. That's of course in addition to the fact that a library can't be responsible for ODR violations introduced by the user. Emil
Le 27/12/2015 17:00, Emil Dotchevski a écrit :
On Sat, Dec 26, 2015 at 5:19 PM, Rob Stewart
wrote: On December 26, 2015 4:54:19 AM EST, Rainer Deyke
wrote: I think, rather than X and Y providing conflicting definitions, the problem is that abc provides a specialization to allow interoperability with def, and def does the same for abc. Using the two libraries, in that case, always creates a conflict. This implies a circular dependency between abc and def. If those
On 25.12.2015 13:03, Rob Stewart wrote: libraries are that tightly coupled, surely they can work out this conflict between themselves? It implies no such thing. It implies that each library provider chose, independently, to offer interoperability with the other using QVM.
It isn't exactly interoperability. The specialization in question isn't needed to make library X and Y compatible with each other using QVM, that's automatic. It only specifies the return type of operator* when multiplying e.g. X::matrix by Y::matrix; and it is plain wrong for X or Y to specify that, because the user most likely wants to get a my_matrix instead. You should document this fact on the documentation. That's of course in addition to the fact that a library can't be responsible for ODR violations introduced by the user.
Any library that allows the user to customize its behavior must define a way that allows the user to avoid ODR violations, otherwise the use of the library by 3pp libraries don't scale. Vicente
Rob Stewart wrote:
On December 26, 2015 4:54:19 AM EST, Rainer Deyke
wrote: I think, rather than X and Y providing conflicting definitions, the problem is that abc provides a specialization to allow interoperability with def, and def does the same for abc. Using the two libraries, in that case, always creates a conflict. This implies a circular dependency between abc and def. If those
On 25.12.2015 13:03, Rob Stewart wrote: libraries are that tightly coupled, surely they can work out this conflict between themselves? It implies no such thing. It implies that each library provider chose, independently, to offer interoperability with the other using QVM.
This would be problematic if interoperability was mandatory in both libraries, i.e. always required. A root cause is that a library may specialize traits for a type from different library. With traits taking two types it's slightly more probable to have a conflict. However with single-type traits this could be the case too. If we assume that both libraries requires interoperability, that they depend on each other, that the developers doesn't communicate with each other, they add QVM dependency at the same time and don't test with development version of the other library then even single-type traits can be a problem. The problem doesn't exist if one of these conditions is not met, e.g. each library specialize traits only for types from this library, makes the interoperability optional, developers communicate with each other, etc. Furthermore the specialization of those deduce_xx traits is not required so I think that in practice it will not be specialized in a great majority of cases. Maybe would it be sufficient to simply describe the potential problems in the documentation? Regards, Adam
On 27.12.2015 00:19, Rob Stewart wrote:
On December 26, 2015 4:54:19 AM EST, Rainer Deyke
wrote: On 25.12.2015 13:03, Rob Stewart wrote:
I think, rather than X and Y providing conflicting definitions, the problem is that abc provides a specialization to allow interoperability with def, and def does the same for abc. Using the two libraries, in that case, always creates a conflict.
This implies a circular dependency between abc and def. If those libraries are that tightly coupled, surely they can work out this conflict between themselves?
It implies no such thing. It implies that each library provider chose, independently, to offer interoperability with the other using QVM.
On a technical level, the only way either library can provide such a specialization is by either including a header from the other library (which counts as a dependency in my book) or by writing its own forward declaration of the types used in the other library (which counts as a dependency on the /implementation/ of the other library in my book). On a more philosophical level, neither library should provide specialize any Boost.QVM templates for types from another library unless one of the following is true: - The library in question requires such specializations as part of its internal workings, i.e. there is a strong, one-way dependency from the library in question to the other library. - The whole point of the library in question is to provide such specializations. In the former case, there are IMO sufficient protections against ODR violations. In the latter case, there is no point in using more than one such library in any given program. -- Rainer Deyke (rainerd@eldwood.com)
On December 28, 2015 7:46:48 AM EST, Rainer Deyke
On 27.12.2015 00:19, Rob Stewart wrote:
On December 26, 2015 4:54:19 AM EST, Rainer Deyke
wrote: On 25.12.2015 13:03, Rob Stewart wrote:
I think, rather than X and Y providing conflicting definitions, the problem is that abc provides a specialization to allow interoperability with def, and def does the same for abc. Using the two libraries, in that case, always creates a conflict.
This implies a circular dependency between abc and def. If those libraries are that tightly coupled, surely they can work out this conflict between themselves?
It implies no such thing. It implies that each library provider chose, independently, to offer interoperability with the other using QVM.
On a technical level, the only way either library can provide such a specialization is by either including a header from the other library (which counts as a dependency in my book) or by writing its own forward declaration of the types used in the other library (which counts as a dependency on the /implementation/ of the other library in my book).
Each can provide an extra header that has the interdependencies. That doesn't mean the libraries have any other dependencies.
On a more philosophical level, neither library should provide specialize any Boost.QVM templates for types from another library unless one of the following is true: - The library in question requires such specializations as part of its internal workings, i.e. there is a strong, one-way dependency from the library in question to the other library. - The whole point of the library in question is to provide such specializations. In the former case, there are IMO sufficient protections against ODR violations. In the latter case, there is no point in using more than one such library in any given program.
I disagree with your assertion that those are the only valid reasons. Each may specialize the trait to specify their own type as the result when the two interact. Any user that combines code that triggers the inclusion of both sets of specializations would lead to an ODR violation, and there would be no clue that it has occurred. That is the danger inherent in such a customization point. ___ Rob (Sent from my portable computation engine)
On 28.12.2015 15:54, Rob Stewart wrote:
Each can provide an extra header that has the interdependencies. That doesn't mean the libraries have any other dependencies.
So, don't include that header.
On a more philosophical level, neither library should provide specialize any Boost.QVM templates for types from another library unless one of the following is true: - The library in question requires such specializations as part of its internal workings, i.e. there is a strong, one-way dependency from the>> library in question to the other library. - The whole point of the library in question is to provide such specializations. In the former case, there are IMO sufficient protections against ODR violations. In the latter case, there is no point in using more than one such library in any given program.
I disagree with your assertion that those are the only valid reasons. Each may specialize the trait to specify their own type as the result when the two interact. Any user that combines code that triggers the inclusion of both sets of specializations would lead to an ODR violation, and there would be no clue that it has occurred. That is the danger inherent in such a customization point.
This is not a valid reason, precisely because it can lead to an ODR violation. -- Rainer Deyke (rainerd@eldwood.com)
On December 29, 2015 4:19:47 AM EST, Rainer Deyke
On 28.12.2015 15:54, Rob Stewart wrote:
Each can provide an extra header that has the interdependencies. That doesn't mean the libraries have any other dependencies.
So, don't include that header.
Of course that's the way to preclude the problem, but it isn't always so easy.
On a more philosophical level, neither library should provide specialize any Boost.QVM templates for types from another library unless one of the following is true: - The library in question requires such specializations as part of its internal workings, i.e. there is a strong, one-way dependency from the>> library in question to the other library. - The whole point of the library in question is to provide such specializations. In the former case, there are IMO sufficient protections against ODR violations. In the latter case, there is no point in using more than one such library in any given program.
I disagree with your assertion that those are the only valid reasons. Each may specialize the trait to specify their own type as the result when the two interact. Any user that combines code that triggers the inclusion of both sets of specializations would lead to an ODR violation, and there would be no clue that it has occurred. That is the danger inherent in such a customization point.
This is not a valid reason, precisely because it can lead to an ODR violation.
Are you being purposely obtuse? If two separate libraries use one each of the specializations, and some new application has need to use both libraries, there will be an ODR violation, most likely without the knowledge of the programmer combining the two libraries. The "validity" of the reason stems from the need to use the two libraries, not from their specializing, or not, the QVM traits. ___ Rob (Sent from my portable computation engine)
Rob Stewart wrote:
Are you being purposely obtuse? If two separate libraries use one each of the specializations, and some new application has need to use both libraries, there will be an ODR violation, most likely without the knowledge of the programmer combining the two libraries. The "validity" of the reason stems from the need to use the two libraries, not from their specializing, or not, the QVM traits.
No, he isn't being obtuse. It is not right for library X to override the return type of X::m * Y::m to be X::m instead of the default, precisely because if we assume that it has this right, the symmetric right of Y to override the same to be Y::m creates a conflict.
On December 29, 2015 12:52:33 PM EST, Peter Dimov
Are you being purposely obtuse? If two separate libraries use one each of the specializations, and some new application has need to use both libraries, there will be an ODR violation, most likely without the knowledge of the programmer combining the two libraries. The "validity" of the reason stems from the need to use the two libraries, not from
Rob Stewart wrote: their
specializing, or not, the QVM traits.
No, he isn't being obtuse. It is not right for library X to override the return type of X::m * Y::m to be X::m instead of the default, precisely because if we assume that it has this right, the symmetric right of Y to override the same to be Y::m creates a conflict.
What if the two libraries that specialize the return type are not related to the two that provide X and Y, but are, say, internal libraries used by different teams? If a third team decides to use the first two teams' libraries together, the problem arises again. The specializations would be reasonable for the first two teams. Only the third team has a problem and you can easily imagine that no one from the first two teams would think of the potential problem to warn the third team. ___ Rob (Sent from my portable computation engine)
On 29.12.2015 22:54, Rob Stewart wrote:
What if the two libraries that specialize the return type are not related to the two that provide X and Y, but are, say, internal libraries used by different teams? If a third team decides to use the first two teams' libraries together, the problem arises again. The specializations would be reasonable for the first two teams. Only the third team has a problem and you can easily imagine that no one from the first two teams would think of the potential problem to warn the third team.
Correct me if I'm wrong, but it to me seems that the root of evil here is a specialization by third party library, by which I mean the case when template from library X is specialized with type(s) exclusively from library (libraries) Y (Y might be the same as X) by library Z (which is neither X nor Y, third party). If it's true, an ODR would be caused for a user even if _unary_ deduce_m (or any other deduce_X) will be specialized by two unrelated third party libraries A and B imported by user. Adding an extra formal type parameter to the template(s) for tag type from library Z would make it safe, but in this case that's pointless as QVM's template machinery would not know which tag to use. If this is a flaw, then many things are also flawed - e.g. overloads by third party too. Also, adaptation of any set of types to any concept by third party. E.g., std::vector is adopted to BGL with boost/graph/vector_as_graph.hpp, but any third party library shall not adopt boost::container::vector; this can only be done by one team. For large teams it seems unmanageable. The question is does it mean that libraries that provide templates for specialization (or overloading) are undesirable? Or can a specialization be just limited in such a way that no third party library (as defined above) shall specialize it? I.e., libraries - only for their own types, users - for anything, given they can find a way to manage this in large projects.
On December 31, 2015 2:42:55 AM EST, Sergey Mitsyn
Correct me if I'm wrong, but it to me seems that the root of evil here is a specialization by third party library, by which I mean the case when template from library X is specialized with type(s) exclusively from library (libraries) Y (Y might be the same as X) by library Z (which is neither X nor Y, third party). If it's true, an ODR would be caused for a user even if _unary_ deduce_m (or any other deduce_X) will be specialized by two unrelated third party libraries A and B imported by user.
Your point is valid except that one-type customization points are likely to be provided by the library providing the type X or Y, or by the library providing the customization point using a separate header (opt in). It's two-type customization points that exist to combine foreign types that pose an issue because they invite multiple definitions. Bold warnings in the documentation may be the only real solution to the issue. ___ Rob (Sent from my portable computation engine)
On 31.12.2015 12:00, Rob Stewart wrote:
On December 31, 2015 2:42:55 AM EST, Sergey Mitsyn
wrote: Correct me if I'm wrong, but it to me seems that the root of evil here is a specialization by third party library, by which I mean the case when template from library X is specialized with type(s) exclusively from library (libraries) Y (Y might be the same as X) by library Z (which is neither X nor Y, third party). If it's true, an ODR would be caused for a user even if _unary_ deduce_m (or any other deduce_X) will be specialized by two unrelated third party libraries A and B imported by user.
Your point is valid except that one-type customization points are likely to be provided by the library providing the type X or Y, or by the library providing the customization point using a separate header (opt in).
But then until they don't it's still an issue, because eventually they may provide, so a specialization made by a library user is a ticking bomb.
Bold warnings in the documentation may be the only real solution to the issue.
___ Rob
(Sent from my portable computation engine)
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Le 31/12/2015 10:24, Sergey Mitsyn a écrit :
On 31.12.2015 12:00, Rob Stewart wrote:
On December 31, 2015 2:42:55 AM EST, Sergey Mitsyn
wrote: Correct me if I'm wrong, but it to me seems that the root of evil here is a specialization by third party library, by which I mean the case when template from library X is specialized with type(s) exclusively from library (libraries) Y (Y might be the same as X) by library Z (which is neither X nor Y, third party). If it's true, an ODR would be caused for a user even if _unary_ deduce_m (or any other deduce_X) will be specialized by two unrelated third party libraries A and B imported by user.
Your point is valid except that one-type customization points are likely to be provided by the library providing the type X or Y, or by the library providing the customization point using a separate header (opt in).
But then until they don't it's still an issue, because eventually they may provide, so a specialization made by a library user is a ticking bomb.
Right. We should expect that the library document the need of such a customization so that the end user can know if s/he can combine it with other libraries. Customization of a class X are expected to be given by the library providing class X, or a friend library. I don't remember if I've already suggested to replace the deduce_xx customizations by a customization that depends only on the first parameter. I don't think this will dismiss a lot the functionality of the library. Vicente
Bold warnings in the documentation may be the only real solution to the issue.
"Need" is too strong, specifying the return type for binary operations is optional. The deduction templates for binary operations must use two parameters because they define the return type specifically for a given pair of argument types. On Thursday, December 31, 2015, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 31/12/2015 10:24, Sergey Mitsyn a écrit :
On 31.12.2015 12:00, Rob Stewart wrote:
On December 31, 2015 2:42:55 AM EST, Sergey Mitsyn
wrote: Correct me if I'm wrong, but it to me seems that the root of evil here is a specialization by third party library, by which I mean the case when template from library X is specialized with type(s) exclusively from library (libraries) Y (Y might be the same as X) by library Z (which is neither X nor Y, third party). If it's true, an ODR would be caused for a user even if _unary_ deduce_m (or any other deduce_X) will be specialized by two unrelated third party libraries A and B imported by user.
Your point is valid except that one-type customization points are likely to be provided by the library providing the type X or Y, or by the library providing the customization point using a separate header (opt in).
But then until they don't it's still an issue, because eventually they may provide, so a specialization made by a library user is a ticking bomb.
Right. We should expect that the library document the need of such a customization so that the end user can know if s/he can combine it with other libraries.
Customization of a class X are expected to be given by the library providing class X, or a friend library.
I don't remember if I've already suggested to replace the deduce_xx customizations by a customization that depends only on the first parameter. I don't think this will dismiss a lot the functionality of the library.
Vicente
Bold warnings in the documentation may be the only real solution to the issue.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
Unary deduction for a type defined by any library isn't a problem since the
specialization reasonably belongs to the library that defines the type.
Operation overloads for third party types won't cause ambiguities with the
generic overloads defined by QVM.
On Thursday, December 31, 2015, Sergey Mitsyn
On 29.12.2015 22:54, Rob Stewart wrote:
What if the two libraries that specialize the return type are not related to the two that provide X and Y, but are, say, internal libraries used by different teams? If a third team decides to use the first two teams' libraries together, the problem arises again. The specializations would be reasonable for the first two teams. Only the third team has a problem and you can easily imagine that no one from the first two teams would think of the potential problem to warn the third team.
Correct me if I'm wrong, but it to me seems that the root of evil here is a specialization by third party library, by which I mean the case when template from library X is specialized with type(s) exclusively from library (libraries) Y (Y might be the same as X) by library Z (which is neither X nor Y, third party). If it's true, an ODR would be caused for a user even if _unary_ deduce_m (or any other deduce_X) will be specialized by two unrelated third party libraries A and B imported by user.
Adding an extra formal type parameter to the template(s) for tag type from library Z would make it safe, but in this case that's pointless as QVM's template machinery would not know which tag to use.
If this is a flaw, then many things are also flawed - e.g. overloads by third party too. Also, adaptation of any set of types to any concept by third party. E.g., std::vector is adopted to BGL with boost/graph/vector_as_graph.hpp, but any third party library shall not adopt boost::container::vector; this can only be done by one team. For large teams it seems unmanageable.
The question is does it mean that libraries that provide templates for specialization (or overloading) are undesirable? Or can a specialization be just limited in such a way that no third party library (as defined above) shall specialize it? I.e., libraries - only for their own types, users - for anything, given they can find a way to manage this in large projects.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
Le 23/12/2015 23:44, Adam Wulkiewicz a écrit :
Emil Dotchevski wrote:
On Wed, Dec 23, 2015 at 6:24 AM, Adam Wulkiewicz
wrote: Vicente J. Botet Escriba wrote:
Le 10/12/2015 08:30, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 10:36 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:15, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba < > vicente.botet@wanadoo.fr> wrote: > > The problem appear when two such programmers do it (think of 3pp). If within one program two programmers introduce two different definitions
under the same name, yes you have ODR but that is hardly a library problem. :)
Hmm. This is a library issue, because the library provides an interface that allows to configure types that don't know each other by two different parts.
TBoost.Conversion was rejected exactly by this reason.
This indeed is an important point, unfortunately I cannot take it into account because it wasn't mentioned in any review. Vincente, do you plan to write one?
If the problem is that QVM allows you to specialize a type template, and that it is possible for two programmers to introduce two different definitions for the same specialization, how is that a library issue? If that's a problem then we can't allow any templates in any library interface, which seems odd.
Basically I think we should clarify this. AFAIU the problem might occur if there were e.g. two libraries (abc and def) providing their own matrix representations (e.g. abc::mat4x4 and def::mat4x4). Then we'd have two other libraries (X and Y) both using those two matrix types together with QVM. So both X and Y libraries would have to specialize QVM traits for abc::mat4x4 and def::mat4x4. Then, if both X and Y libraries were included in a program there would be problems since the specializations of QVM traits would be duplicated. I'm not sure if we could do anything about it because similar problem would occur every time when any traits was required by any library. So AFAIU this is what Emil is saying.
Or are deduce_xx traits somehow different than other QVM traits?
Vincente is this what you had in mind or was it a different issue?
Hi, yes, this is exactly the case. Vicente
2015-12-29 1:30 GMT+01:00 Vicente J. Botet Escriba : Le 23/12/2015 23:44, Adam Wulkiewicz a écrit : AFAIU the problem might occur if there were e.g. two libraries (abc and
def) providing their own matrix representations (e.g. abc::mat4x4 and
def::mat4x4). Then we'd have two other libraries (X and Y) both using those
two matrix types together with QVM. So both X and Y libraries would have to
specialize QVM traits for abc::mat4x4 and def::mat4x4. Then, if both X and
Y libraries were included in a program there would be problems since the
specializations of QVM traits would be duplicated. I'm not sure if we could
do anything about it because similar problem would occur every time when
any traits was required by any library. So AFAIU this is what Emil is
saying. Or are deduce_xx traits somehow different than other QVM traits? Vincente is this what you had in mind or was it a different issue? Hi, yes, this is exactly the case. Emil, do you think that the deduce_xx traits are something that is crucial
for the library? Or could it be e.g. hidden in the details?
I'm asking because in general in QVM return types are hidden from the user
and only if the user wants to do something special he must e.g. overload an
operator or a function. Why not rely on this mechanism also in this case?
Furthermore AFAIU two-argument deduce_xx are only used in operations taking
operands of the same kind and returning a result of the same kind as the
operands, where "kind" means "type adapted to the same concept", e.g.
matrix from two matrices, vector from two vectors, etc. So while the
coverage is quite good operations taking various kinds of arguments like
e.g. a vector and a scalar generating a matrix are not covered. In such
cases the library can return any type, right?
So I'm wondering, would it be a good idea to simply pick some good default
and simply rely on overloading if something fancy was needed?
The default could be the same type for two operands of the same type, and
something unspecified in other cases, so the same as it is now.
Regards,
Adam
On Wed, Dec 30, 2015 at 11:39 AM, Adam Wulkiewicz wrote: Emil, do you think that the deduce_xx traits are something that is crucial
for the library? Or could it be e.g. hidden in the details? Without this machinery it wouldn't be possible to customize the return type
for binary operations invoked with different user-defined types.
Specializing this template also helps avoid temporaries. I'm asking because in general in QVM return types are hidden from the user
and only if the user wants to do something special he must e.g. overload an
operator or a function. Why not rely on this mechanism also in this case? I'm not sure what you mean by "hidden from the user". For example, matrix
multiplication is documented like this:
//Only enabled if:
// is_m<A>::value && is_m<B>::value &&
// m_traits<A>::cols==m_traits<B>::rows
template operands of the same kind and returning a result of the same kind as the
operands, where "kind" means "type adapted to the same concept", e.g.
matrix from two matrices, vector from two vectors, etc. So while the
coverage is quite good operations taking various kinds of arguments like
e.g. a vector and a scalar generating a matrix are not covered. In such
cases the library can return any type, right? deduce_m is used by unary operations that need to deduce the return matrix
type from the type passed as the argument.
deduce_m2 is used by binary operations that need to deduce the return
matrix type from the two types passed as arguments.
This is the complete list of return type deduction templates, by analogy:
- for quaternions: deduce_q/q2;
- for vectors: deduce_v/v2;
- for matrices: deduce_m/m2;
- for scalars: deduce_s. So I'm wondering, would it be a good idea to simply pick some good default
and simply rely on overloading if something fancy was needed?
The default could be the same type for two operands of the same type, and
something unspecified in other cases, so the same as it is now. There is a good default type, just don't specialize deduce_m2. See
http://zajo.github.io/boost-qvm/deduce_m2.html.
Emil
Le 31/12/2015 06:20, Emil Dotchevski a écrit :
On Wed, Dec 30, 2015 at 11:39 AM, Adam Wulkiewicz
wrote: Emil, do you think that the deduce_xx traits are something that is crucial for the library? Or could it be e.g. hidden in the details?
Without this machinery it wouldn't be possible to customize the return type for binary operations invoked with different user-defined types. Specializing this template also helps avoid temporaries. What about customizing it with the fist argument only?
Vicente
Le 23/12/2015 21:09, Emil Dotchevski a écrit :
On Wed, Dec 23, 2015 at 6:24 AM, Adam Wulkiewicz
wrote: Vicente J. Botet Escriba wrote:
Le 10/12/2015 08:30, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 10:36 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:15, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 2:51 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:
The problem appear when two such programmers do it (think of 3pp). If within one program two programmers introduce two different definitions
under the same name, yes you have ODR but that is hardly a library problem. :)
Hmm. This is a library issue, because the library provides an interface that allows to configure types that don't know each other by two different parts.
TBoost.Conversion was rejected exactly by this reason.
This indeed is an important point, unfortunately I cannot take it into account because it wasn't mentioned in any review. Vincente, do you plan to write one?
If the problem is that QVM allows you to specialize a type template, and that it is possible for two programmers to introduce two different definitions for the same specialization, how is that a library issue? If that's a problem then we can't allow any templates in any library interface, which seems odd.
I believe there is a difference between traits and the way your library is providing the customization. IMHO, trait<T> specializations should be provided by the library that defines the type T. Your library is promoting that some 3pp libraries do the trait<T> specialization and so it is promoting ODR violation. Note that I'm not saying that your library is not useful in certain contexts (as it was TBoost.Conversion), just that the user of the library must be aware of this problem. Vicente
On December 23, 2015 9:24:04 AM EST, Adam Wulkiewicz
Vicente J. Botet Escriba wrote:
[snip]
TBoost.Conversion was rejected exactly by this reason.
This indeed is an important point, unfortunately I cannot take it into account because it wasn't mentioned in any review.
That is not true. Comments raised during the review can carry all the weight that you, the Review Manager, choose to assign. ___ Rob (Sent from my portable computation engine)
participants (7)
-
Adam Wulkiewicz
-
Emil Dotchevski
-
Peter Dimov
-
Rainer Deyke
-
Rob Stewart
-
Sergey Mitsyn
-
Vicente J. Botet Escriba