red floyd <no.spam@its.invalid>: Mar 28 07:01PM -0700 On 3/28/20 1:51 PM, Jorgen Grahn wrote: >> large. The problem to me appears to be that library algorithms only >> work on iterators. > Seems to me the real problem is you don't have iterators over [1, N). TBH, I'm surprised the Committee hasn't addressed this. |
Ned Latham <nedlatham@woden.valhalla.oz>: Mar 28 09:14PM -0500 red floyd wrote: > > > work on iterators. > > Seems to me the real problem is you don't have iterators over [1, N). > TBH, I'm surprised the Committee hasn't addressed this. Can you construct a dummy object for the iterator's sake? |
danielaparker@gmail.com: Mar 28 08:44PM -0700 On Saturday, March 28, 2020 at 2:04:11 PM UTC-4, red floyd wrote: > I was looking for a way to use standard algorithms with a range of > integers. Option 1: #include <iterator> #include <algorithm> template <class Iterator,class Enable = void> class integer_iterator { }; template <class T> class integer_iterator<T,typename std::enable_if<std::is_integral<T>::value >::type> { T value_; T step_; public: using iterator_category = std::random_access_iterator_tag; using value_type = T; using difference_type = std::ptrdiff_t; using pointer = typename std::conditional<std::is_const<T>::value, value_type*, const value_type*>::type; using reference = typename std::conditional<std::is_const<T>::value, value_type&, const value_type&>::type; public: explicit integer_iterator(T n = 0, T step = 1) : value_(n), step_(step) { } integer_iterator(const integer_iterator&) = default; integer_iterator(integer_iterator&&) = default; integer_iterator& operator=(const integer_iterator&) = default; integer_iterator& operator=(integer_iterator&&) = default; template <class U, class=typename std::enable_if<!std::is_same<U,T>::value && std::is_convertible<U,T>::value>::type> integer_iterator(const integer_iterator<U>& other) : value_(other.value_) { } reference operator*() const { return value_; } T operator->() const { return &value_; } integer_iterator& operator++() { value_ += step_; return *this; } integer_iterator operator++(int) { integer_iterator temp = *this; ++*this; return temp; } integer_iterator& operator--() { value_ -= step_; return *this; } integer_iterator operator--(int) { integer_iterator temp = *this; --*this; return temp; } integer_iterator& operator+=(const difference_type offset) { value_ += offset; return *this; } integer_iterator operator+(const difference_type offset) const { integer_iterator temp = *this; return temp += offset; } integer_iterator& operator-=(const difference_type offset) { return *this += -offset; } integer_iterator operator-(const difference_type offset) const { integer_iterator temp = *this; return temp -= offset; } difference_type operator-(const integer_iterator& rhs) const { return value_ - rhs.value_; } reference operator[](const difference_type offset) const { return *(*this + offset); } bool operator==(const integer_iterator& rhs) const { return value_ == rhs.value_; } bool operator!=(const integer_iterator& rhs) const { return !(*this == rhs); } bool operator<(const integer_iterator& rhs) const { return value_ < rhs.value_; } bool operator>(const integer_iterator& rhs) const { return rhs < *this; } bool operator<=(const integer_iterator& rhs) const { return !(rhs < *this); } bool operator>=(const integer_iterator& rhs) const { return !(*this < rhs); } inline friend integer_iterator<T> operator+( difference_type offset, integer_iterator<T> next) { return next += offset; } }; int main(int argc, char** argv) { integer_iterator<int> first(1,10); integer_iterator<int> last(100000001, 10); int n = 0; auto f = [&n](int i) {n += i;}; std::for_each(first, last, f); } Option 2 int main(int argc, char** argv) { int n = 0; auto f = [&n](int i) {n += i;}; for (int i = 1; i < 100000001; i += 10) { f(i); } } Decisions, decisions ... Daniel |
red floyd <no.spam@its.invalid>: Mar 28 11:04AM -0700 I was looking for a way to use standard algorithms with a range of integers. For example, for the range [1, N), where N can be arbitrarily large. The problem to me appears to be that library algorithms only work on iterators. I didn't want to just create a collection containing the integers, because I was playing with some math which might use large values (on the order of over a million), and I didn't want to waste the space. So for my purposes, I came up with the following. [BEGIN CODE] namespace my { template<typename Integral, typename UnaryFunction> Integral for_each(Integral first, Integral last, UnaryFunction func) { while (first < last) { func(first); ++first; } return first; } template<typename Integral, typename UnaryFunction> Integral for_each(Integral first, Integral last, Integral interval, UnaryFunction func) { while (first < last) { func(first); first += interval; } return first; } } [END CODE] I don't want to duplicate something already written, is there something similar in the Standard Library? -- red floyd |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 29 02:46PM +0200 On 28.03.2020 19:04, red floyd wrote: > [END CODE] > I don't want to duplicate something already written, is there > something similar in the Standard Library? In C++20 there will be std::something::idiota, or "iota" as the Greeks tend to shorten it, used like for( const int i: idiota( n ) ) do { //... use `i` here With the under-construction-library-that-I-really-need-to-finish-sometime you can write similar but much more clear code like for( const int i: zero_to( n ) ) { //... Use `i` here. <url: https://github.com/alf-p-steinbach/cppx-core-language/blob/master/source/cppx-core-language/syntax/collection-util/Sequence_.hpp>. This is not an `idiota` copy; the library and concept, though not this particular implementation, predates `idiota` by many years. There are good reasons for all the shenanigans in that code, so it illustrates what you're dealing with for defining a general integers iterator. There may still be bugs. It's not extensively tested. - Alf |
Bonita Montero <Bonita.Montero@gmail.com>: Mar 28 08:30PM +0100 You could use an iterator which wraps a normal iterator and includes a gap-value. Something like this (don't know if everything is correct): #include <iterator> template<typename RandIt> struct gap_iterator { using value_type = typename std::iterator_traits<RandIt>::value_type; gap_iterator() = default; gap_iterator( RandIt it, std::size_t gap ); gap_iterator( gap_iterator const &other ); gap_iterator &operator =( gap_iterator const &rhs ); bool operator !=( gap_iterator const &other ); value_type &operator *(); value_type *operator ->(); gap_iterator &operator ++(); gap_iterator &operator +=( std::size_t offset ); private: RandIt m_it; size_t m_gap; }; template<typename RandIt> inline gap_iterator<RandIt>::gap_iterator( RandIt it, std::size_t gap ) { m_it = it; m_gap = gap; } template<typename RandIt> inline gap_iterator<RandIt>::gap_iterator( gap_iterator const &other ) { m_it = other.m_it; m_gap = other.m_gap; } template<typename RandIt> inline typename gap_iterator<RandIt>::gap_iterator &gap_iterator<RandIt>::operator =( gap_iterator const &rhs ) { m_it = rhs.m_it; m_gap = rhs.m_gap; return *this; } template<typename RandIt> inline bool gap_iterator<RandIt>::operator !=( gap_iterator const &rhs ) { return m_it != rhs.m_it; } template<typename RandIt> inline typename gap_iterator<RandIt>::value_type &gap_iterator<RandIt>::operator *() { return *m_it; } template<typename RandIt> inline typename gap_iterator<RandIt>::value_type *gap_iterator<RandIt>::operator ->() { return &*m_it; } template<typename RandIt> inline gap_iterator<RandIt> &gap_iterator<RandIt>::operator ++() { m_it += m_gap; return *this; } template<typename RandIt> inline gap_iterator<RandIt> &gap_iterator<RandIt>::operator +=( std::size_t offset ) { m_it += offset * m_gap; return *this; } #include <iostream> #include <algorithm> #include <cstdlib> using namespace std; int main() { int ai[16 * 16]; gap_iterator<int *> giiBegin( ai, 16 ), giiEnd( giiBegin ); giiEnd += 16; for_each( giiBegin, giiEnd, []( int &v ) { v = rand(); } ); for_each( giiBegin, giiEnd, []( int v ) { cout << v << " "; } ); } |
Bonita Montero <Bonita.Montero@gmail.com>: Mar 28 08:46PM +0100 Why does this changed version not work ? #include <iterator> template<typename RandIt> struct gap_iterator { using value_type = typename std::iterator_traits<RandIt>::value_type; gap_iterator() = default; gap_iterator( RandIt it, std::size_t gap ); gap_iterator( gap_iterator const &other ); gap_iterator &operator =( gap_iterator const &rhs ); bool operator !=( gap_iterator const &other ); value_type &operator *(); value_type *operator ->(); gap_iterator &operator ++(); gap_iterator &operator +=( std::size_t offset ); friend gap_iterator operator +( gap_iterator const &gi, std::size_t offset ); private: RandIt m_it; size_t m_gap; }; template<typename RandIt> inline gap_iterator<RandIt>::gap_iterator( RandIt it, std::size_t gap ) { m_it = it; m_gap = gap; } template<typename RandIt> inline gap_iterator<RandIt>::gap_iterator( gap_iterator const &other ) { m_it = other.m_it; m_gap = other.m_gap; } template<typename RandIt> inline typename gap_iterator<RandIt>::gap_iterator &gap_iterator<RandIt>::operator =( gap_iterator const &rhs ) { m_it = rhs.m_it; m_gap = rhs.m_gap; return *this; } template<typename RandIt> inline bool gap_iterator<RandIt>::operator !=( gap_iterator const &rhs ) { return m_it != rhs.m_it; } template<typename RandIt> inline typename gap_iterator<RandIt>::value_type &gap_iterator<RandIt>::operator *() { return *m_it; } template<typename RandIt> inline typename gap_iterator<RandIt>::value_type *gap_iterator<RandIt>::operator ->() { return &*m_it; } template<typename RandIt> inline gap_iterator<RandIt> &gap_iterator<RandIt>::operator ++() { m_it += m_gap; return *this; } template<typename RandIt> inline gap_iterator<RandIt> &gap_iterator<RandIt>::operator +=( std::size_t offset ) { m_it += offset * m_gap; return *this; } template<typename RandIt> inline gap_iterator<RandIt> operator +( gap_iterator<RandIt> const &gi, std::size_t offset ) { gap_iterator<RandIt> ret( gi ); gi.m_it += offset * gi.m_gap; return ret; } #include <iostream> #include <algorithm> #include <cstdlib> using namespace std; int main() { int ai[16 * 16]; gap_iterator<int *> giiBegin( ai, 16 ), giiEnd( giiBegin + 16 ); //giiEnd += 16; for_each( giiBegin, giiEnd, []( int &v ) { v = rand(); } ); for_each( giiBegin, giiEnd, []( int v ) { cout << v << " "; } ); } |
Bonita Montero <Bonita.Montero@gmail.com>: Mar 28 08:47PM +0100 > gi.m_it += offset * gi.m_gap; ret.m_it += offset * ret.m_gap; |
Bonita Montero <Bonita.Montero@gmail.com>: Mar 28 08:49PM +0100 Am 28.03.2020 um 20:47 schrieb Bonita Montero: >> gi.m_it += offset * gi.m_gap; > ret.m_it += offset * ret.m_gap; ret.m_it = ret.m_it + offset * ret.m_gap; The contained iterator might not know +=. |
Bonita Montero <Bonita.Montero@gmail.com>: Mar 28 08:58PM +0100 Got it: #include <iterator> template<typename RandIt> struct gap_iterator { using value_type = typename std::iterator_traits<RandIt>::value_type; gap_iterator() = default; gap_iterator( RandIt it, std::size_t gap ); gap_iterator( gap_iterator const &other ); gap_iterator &operator =( gap_iterator const &rhs ); bool operator !=( gap_iterator const &other ); value_type &operator *(); value_type *operator ->(); gap_iterator &operator ++(); gap_iterator &operator +=( std::size_t offset ); template<typename RandIt> friend gap_iterator<RandIt> operator +( gap_iterator<RandIt> const &gi, std::size_t offset ); private: RandIt m_it; size_t m_gap; }; template<typename RandIt> inline gap_iterator<RandIt>::gap_iterator( RandIt it, std::size_t gap ) { m_it = it; m_gap = gap; } template<typename RandIt> inline gap_iterator<RandIt>::gap_iterator( gap_iterator const &other ) { m_it = other.m_it; m_gap = other.m_gap; } template<typename RandIt> inline typename gap_iterator<RandIt>::gap_iterator &gap_iterator<RandIt>::operator =( gap_iterator const &rhs ) { m_it = rhs.m_it; m_gap = rhs.m_gap; return *this; } template<typename RandIt> inline bool gap_iterator<RandIt>::operator !=( gap_iterator const &rhs ) { return m_it != rhs.m_it; } template<typename RandIt> inline typename gap_iterator<RandIt>::value_type &gap_iterator<RandIt>::operator *() { return *m_it; } template<typename RandIt> inline typename gap_iterator<RandIt>::value_type *gap_iterator<RandIt>::operator ->() { return &*m_it; } template<typename RandIt> inline gap_iterator<RandIt> &gap_iterator<RandIt>::operator ++() { m_it += m_gap; return *this; } template<typename RandIt> inline gap_iterator<RandIt> &gap_iterator<RandIt>::operator +=( std::size_t offset ) { m_it += offset * m_gap; return *this; } template<typename RandIt> inline gap_iterator<RandIt> operator +( gap_iterator<RandIt> const &gi, std::size_t offset ) { gap_iterator<RandIt> ret( gi ); ret.m_it = ret.m_it + offset * ret.m_gap; return ret; } #include <iostream> #include <algorithm> #include <cstdlib> using namespace std; int main() { int ai[16 * 16]; gap_iterator<int *> giiBegin( ai, 16 ), giiEnd( giiBegin + 16 ); //giiEnd += 16; for_each( giiBegin, giiEnd, []( int &v ) { v = rand(); } ); for_each( giiBegin, giiEnd, []( int v ) { cout << v << " "; } ); } |
"Öö Tiib" <ootiib@hot.ee>: Mar 28 05:29PM -0700 On Sunday, 29 March 2020 00:25:27 UTC+2, James Kuyper wrote: > n3797.pdf, dated 2013-10-13, drops that item from the list. > So it would appear that the change you're complaining about took place > about 7-8 years ago. I am really not complaining about that since my constexpr functions don't throw ... it is just another inconvenience. Are these now ill-formed constant expressions instead of being non-constant expressions? I am complaining that constant expression is not detectable with code. So I must keep track if something evaluates to constant expression or not as monkey-coder; I can't make code that does it automatically. The requirement that was useful that noexcept was required to return true to calls that were constant expressions was removed. Things that I do not see much use for in their current form: std::is_constant_evaluated, constinit and consteval were added. |
David Brown <david.brown@hesbynett.no>: Mar 29 10:24AM +0200 On 28/03/2020 20:42, Öö Tiib wrote: > constant expression". So if foo(43) is not constant expression but > foo(42) is then noexcept(foo(43)) should be false and noexcept(foo(42)) > true. As I said - noexcept() has never been about detecting constant expressions. I understand that you think it's odd that a constant expression can return "false" for noexcept. But that is beside the point. You claimed the change to noexcept() broke the tool for detecting constant expressions. I was hoping for a justification for that, rather than another side-track. |
David Brown <david.brown@hesbynett.no>: Mar 29 10:31AM +0200 On 28/03/2020 21:16, Öö Tiib wrote: >> compile-time programming. > It does not work and so you are under some kind of illusion from > worm-tongue-wording of standard. I haven't read the standard here yet. But I must admit I assumed that std::is_constant_evaluated() was basically a standardisation of the useful gcc extension __builtin_constant_p(...). Unfortunately, it is not. |
"Öö Tiib" <ootiib@hot.ee>: Mar 29 01:47AM -0700 On Sunday, 29 March 2020 11:24:47 UTC+3, David Brown wrote: > > foo(42) is then noexcept(foo(43)) should be false and noexcept(foo(42)) > > true. > As I said - noexcept() has never been about detecting constant expressions. But C++ has never been what you said but it is always been what standard said. And C++14 said that noexcept operator should detect constant expressions: The result of the noexcept operator is false if in a potentially-evaluated context the expression would contain - a potentially-evaluated call83 to a function, member function, function pointer, or member function pointer that does not have a non-throwing exception-specification ([except.spec]), unless the call is a constant expression ([expr.const]), > I understand that you think it's odd that a constant expression can > return "false" for noexcept. But that is beside the point. You misrepresent. I do think it's odd that such change was made and hastily implemented in all compilers with retroactive effect in C++11 and C++14 modes too. Despite in C++11 and C++14 the noexcept operator was required to detect constant expressions. > You claimed the change to noexcept() broke the tool for detecting > constant expressions. I was hoping for a justification for that, rather > than another side-track. I do not even understand what you expect. Some kind of philosophical debate? Facts are there. I do not know justifications to those facts. |
"Öö Tiib" <ootiib@hot.ee>: Mar 29 02:08AM -0700 On Sunday, 29 March 2020 11:31:29 UTC+3, David Brown wrote: > But I must admit I assumed that std::is_constant_evaluated() was > basically a standardisation of the useful gcc extension > __builtin_constant_p(...). Unfortunately, it is not. Also __builtin_constant_p does not work. Only noexcept did but stopped. Linus Torvalds trying to figure fixes to __builtin_constant_p : https://lkml.org/lkml/2018/3/17/184 |
David Brown <david.brown@hesbynett.no>: Mar 29 11:38AM +0200 On 29/03/2020 10:47, Öö Tiib wrote: > But C++ has never been what you said but it is always been what standard > said. And C++14 said that noexcept operator should detect constant > expressions: No! C++14 and earlier said constant expressions were /part/ of the logic in determining the result of the noexcept operator. That does not mean, as you have been claiming, that noexcept is a tool for determining if something is a constant expression. > and hastily implemented in all compilers with retroactive effect in > C++11 and C++14 modes too. Despite in C++11 and C++14 the noexcept > operator was required to detect constant expressions. I guess the prevailing opinion (of those who know about these things, unlike me) is that the earlier behaviour was a mistake. >> than another side-track. > I do not even understand what you expect. Some kind of philosophical > debate? Facts are there. I do not know justifications to those facts. Neither the facts, the standards (earlier or later versions), nor what you have now written support the idea that noexcept() was a way to identify constant expressions, or that the changes broke such methods, or that the changes were made maliciously, callously, or without careful consideration. |
David Brown <david.brown@hesbynett.no>: Mar 29 11:48AM +0200 On 29/03/2020 11:08, Öö Tiib wrote: > Also __builtin_constant_p does not work. Only noexcept did but stopped. > Linus Torvalds trying to figure fixes to __builtin_constant_p : > https://lkml.org/lkml/2018/3/17/184 What do you mean, "__builtin_constant_p does not work" ? It works perfectly well, and I have used it - as have many people. It might not do what you think in all cases, such as the one Torvalds is describing - but see the follow-ups for an explanation of that. Perhaps what you mean is "It does not work for my particular case, while an abuse of noexcept() happened to work. But I won't tell anyone the details." |
"Öö Tiib" <ootiib@hot.ee>: Mar 29 03:27AM -0700 On Sunday, 29 March 2020 12:39:01 UTC+3, David Brown wrote: > determining the result of the noexcept operator. That does not mean, as > you have been claiming, that noexcept is a tool for determining if > something is a constant expression. It was the only thing in standard that had requirement of detecting if something is constant expression, makeing nothing ill-formed doing so and returning constant expression itself. Nothing else (including non-standard __builtin_constant_p) had those properties. So it was useful as such tool but now it isn't. > > operator was required to detect constant expressions. > I guess the prevailing opinion (of those who know about these things, > unlike me) is that the earlier behaviour was a mistake. It is void argument to me. I have just my work to do and I want to do it well. You post zero code how I should do it now, just popular votes and alleged opinions of your "authorities". > identify constant expressions, or that the changes broke such methods, > or that the changes were made maliciously, callously, or without careful > consideration. I would probably be "fixed" too by now if I had direct evidence about malice. Forces that can enforce retroactive "fixes" in all compilers have enough resources to "fix" people too. But mine is just opinion based on facts there are. |
"Öö Tiib" <ootiib@hot.ee>: Mar 29 03:33AM -0700 On Sunday, 29 March 2020 12:48:51 UTC+3, David Brown wrote: > Perhaps what you mean is "It does not work for my particular case, while > an abuse of noexcept() happened to work. But I won't tell anyone the > details." You unlike me are posting zero code, quotes and/or cites. So I feel your posture that I am withholding details insulting. |
David Brown <david.brown@hesbynett.no>: Mar 29 01:56PM +0200 On 29/03/2020 12:33, Öö Tiib wrote: >> details." > You unlike me are posting zero code, quotes and/or cites. So I feel your > posture that I am withholding details insulting. I am not posting code, because I don't have a problem with any code. This whole discussion started with /your/ claim that C++20 breaks volatile and makes it impossible to write low-level code that uses it. What would you like me to post - code that has a volatile variable and writes to it? #define output_register *((volatile uint32_t *) 0x1234) void set_output(uint32_t x) { output_register = x; } That works fine in every C and C++ standard. I don't have any sample code with noexcept, because I disable exceptions in my embedded C++ code. (Yes, I know that is a non-conforming extension in my compiler.) /You/ are the one with complaints about the standards and how changes break your code. /You/ are the one that said C++20 changes volatile and breaks your code - the onus is on /you/ to post code that shows this effect. /You/ are the one that said C++17 changes noexcept and breaks your code (though I still haven't a clue how that relates to your complain about "volatile"). I can't give any code snippets or references to problems with volatile or noexcept, because I don't have any problems. I can't give any code snippets or references regarding /your/ problems with volatile and noexcept, because you won't say what they are or show examples. You have given some references, but no indication as to why they are relevant. If you want to warn people about standards changes that break real, useful code, then post some examples so that we can learn. If you want to get help making your code robust in the face of changes, post some samples so that we can help. (I am not guaranteeing help, and I am sure others would be more helpful than I could be - but at least people can try.) If you want to complain about the changes causing you trouble, post some examples so that we can see the problem and sympathise, and possibly make useful guesses as to the reason behind the changes. We all know the C++ committee and compiler writers are mere humans and make mistakes. If you want to convince people that you have misunderstood the changes, or that you have been writing weird code that merely happens to work by luck, then continue posting red-herrings, mixing up topics, claiming malice and incompetence on the part of the committees and compiler writers, and failing to answer direct questions or show samples. If that's the way you want to play it, I am done here - I can't see any way to make progress. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Mar 28 01:22PM -0400 On 3/28/20 11:44 AM, David Brown wrote: > On 27/03/2020 19:52, Öö Tiib wrote: ... > (This is based on my understanding and reasoning, rather than the > standards - frankly, I haven't managed to get my head around the > standards here as yet.) "The predicate indicating whether a function cannot exit via an exception is called the exception specification of the function. If the predicate is false, the function has a potentially-throwing exception specification, otherwise it has a non-throwing exception specification. The exception specification is either defined implicitly, or defined explicitly by using a noexcept-specifier as a suffix of a function declarator (11.3.5). noexcept-specifier: noexcept ( constant-expression ) noexcept throw ( )" (18.4p1). Note that the phrases "exception specification", "potentially-throwing exception specification" and "non-throwing exception specification" are all italicized, an ISO convention indicating that this clause constitutes the official definition of those terms. Therefore, the value of a noexcept() expression is determined entirely by the exception specification of the function. The body of the function plays no role in determining that value, not even if it's declared inline in the same translation unit. ... > consider it imaginary. (I believe that this is due to your > misunderstandings about what the changes to volatile in C++20 mean, not > because I think you are being deliberately awkward.) That's why we both keep asking him to provide examples - so we can say to him "such code will not be deprecated in C++2020". |
"Öö Tiib" <ootiib@hot.ee>: Mar 29 05:30AM -0700 On Sunday, 29 March 2020 14:56:31 UTC+3, David Brown wrote: > > You unlike me are posting zero code, quotes and/or cites. So I feel your > > posture that I am withholding details insulting. > I am not posting code, because I don't have a problem with any code. So when I am posting code that stopped working for me then you reply that it was weird trash anyway that merely worked by luck while it was clearly mandated by C++14 standard to work. You do not post where I supposedly misinterpreted standard nor advice how should I write the code instead nor any explanations why it was retroactively "fixed" in all compilers. Just insults. What "help" is that? |
David Brown <david.brown@hesbynett.no>: Mar 28 08:35PM +0100 On 28/03/2020 18:42, Öö Tiib wrote: > So fine, I am just stupid and silly when I complain that our tools were > clearly and deliberately damaged. Damaged with unprecedented retroactive > effect in C++11 and C++14 modes as well. noexcept() has never been about "detecting constant expressions"! Until C++20, there was no way of detecting constant expressions. Now there is "is_constant_evaluated", constinit and consteval. To my mind, C++20 has significantly improved the scope for constant expressions and compile-time programming. > possibility to detect volatile this with overload resolution. > You have technically already rejected usefulness of it with your > praise of changes and don't see value in it. I have asked you repeatedly to show an example that /you/ think is good code design, and which relies on a feature of volatile that is (or which you think is) deprecated in C++20. I have not asked you to show code you think /I/ will like - that would be entirely unreasonable. > constant expressions weren't made detectable with some > std::is_constexpr(foo(42)) but it wasn't needed as there was possible > to write it using noexcept. You are conflating three completely separate concepts here. noexcept() has nothing to do with detecting constant expressions. And neither of these is remotely connected with volatile or the changes to volatile in C++20. I am still unsure as to whether you have misunderstood something in C++20 (or perhaps in an earlier version), or if you have a point which you are failing to demonstrate. Until we get an example, no one can tell. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Mar 28 03:38PM -0400 On 3/28/20 1:42 PM, Öö Tiib wrote: > On Saturday, 28 March 2020 17:45:09 UTC+2, David Brown wrote: ... >> misunderstandings about what the changes to volatile in C++20 mean, not >> because I think you are being deliberately awkward.) > The change deprecates volatile qualified member functions and so P1152R0 mentions deprecating volatile-qualified member functions. The notes concerning the changes between r0 and r1 list the results of votes on several different issues involving volatile-qualified member functions, all but one of which was approved. However, in r4, I can find no other mention of deprecating them. Can you point me to the clause (in P1152R4) where that occurs? |
James Kuyper <jameskuyper@alumni.caltech.edu>: Mar 28 03:54PM -0400 On 3/28/20 3:42 PM, Öö Tiib wrote: > constant expression". So if foo(43) is not constant expression but > foo(42) is then noexcept(foo(43)) should be false and noexcept(foo(42)) > true. A call to a constexpr function whose definition has been provided, has defined behavior, and which meets the requirements for a constexpr function (10.1.5) doesn't match any of the items in the list under 8.20p2 - as such, it can never fail to qualify as a constant expression, regardless of which value is passed to the function. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment