4

So the order of the members returned from the div functions seems to be implementation defined.

Is quot the 1st member or is rem?

Let's say that I'm doing something like this:

generate(begin(digits), end(digits), [i = div_t{ quot, 0 }]() mutable {
    i = div(i.quot, 10);
    return i.rem;
})

Of course the problem here is that I don't know if I initialized i.quot or i.rem in my lambda capture. Is intializing i with div(quot, 1) the only cross platform way to do this?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288

6 Answers6

8

You're right that the order of the members is unspecified. The definition is inherited from C, which explicitly states it is (emphasis mine):

7.20.6.2 The div, ldiv, and lldiv functions

3 [...] The structures shall contain (in either order) the members quot (the quotient) and rem (the remainder), each of which has the same type as the arguments numer and denom. [...]

In C, the fact that the order is unspecified doesn't matter, and an example is included specifically regarding div_t:

6.7.8 Initialization

34 EXAMPLE 10 Structure members can be initialized to nonzero values without depending on their order:

div_t answer = { .quot = 2, .rem = -1 };

Unfortunately, C++ never adopted this syntax.

I'd probably go for simple assignment in a helper function:

div_t make_div_t(int quot, int rem) {
  div_t result;
  result.quot = quot;
  result.rem = rem;
  return result;
}

For plain int values, whether you use initialisation or assignment doesn't really matter, they have the same effect.

Your division by 1 is a valid option as well.

Community
  • 1
  • 1
2

To quote the C11 Standard Draft N1570 §7.22.6.2

The div, ldiv, and lldiv functions return a structure of type div_t, ldiv_t, and lldiv_t, respectively, comprising both the quotient and the remainder. The structures shall contain (in either order) the members quot (the quotient) and rem (the remainder), each of which has the same type as the arguments numer and denom.

So in this case div_t is a plain POD struct, consisting of two ints.

So you can initialize it like every plain struct, your way would be something I would have done too. It's also portable.

Otherwise I can't find anything special mechanism to initialize them, neither in the C nor in the C++ standard. But for POD aka Plain Old Datatypes, there isn't any need for.

Superlokkus
  • 4,731
  • 1
  • 25
  • 57
  • The whole point of the question is that either `quot` or `rem` could be the first member, and the quote you provided (and I did as well) makes it explicit that the OP's concern is justified. This does not at all support your conclusion that initialising it using `{quot, rem}` is just fine. It's valid, but it won't necessarily do what the OP wants. –  Jan 09 '17 at 20:40
  • @hvd Sadly you're right, I was only thinking about zero initialization – Superlokkus Jan 09 '17 at 20:43
1

Try something like this:)

int quot = 10;
auto l = [i = [=] { div_t tmp{}; tmp.quot = quot; return tmp; }()]() mutable
{
    i = div(i.quot, 10);
    return i.rem;
};

It looks like using a compound literal in C.:)

or you can simplify the task by defining the variable i outside the lambda expression and use it in the lambda by reference.

For example

int quot = 10;
dov_t i = {};
i.quot = quot;

auto l = [&i]()
{
    i = div(i.quot, 10);
    return i.rem;
};
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Gah! It's lambda-ception. Not sure if that joke works here but I tried. Anyway, the answers seem to indicate that member initialization is my only way forward :( – Jonathan Mee Jan 10 '17 at 12:47
  • @JonathanMee An evaluated lambda expression is an expression. So there is no problem. It must to work. The value of the expression is an object of type div_t. – Vlad from Moscow Jan 10 '17 at 13:01
1

EDIT:

I think the VS workaround could look like this:

#include <cstdlib>
#include <type_traits>

template<class T>
struct DTMaker {
 using D = decltype(div(T{}, T{}));
 static constexpr D dt = D{0,1};
 static constexpr auto quot = dt.quot;
};

template <class T, typename std::enable_if<DTMaker<T>::quot == 0>::type* = nullptr>
typename DTMaker<T>::D make_div(const T &quot, const T& rem) { return {quot, rem}; }

template <class T, typename std::enable_if<DTMaker<T>::quot == 1>::type* = nullptr>
typename DTMaker<T>::D make_div(const T &quot, const T &rem) { return {rem, qout}; }

int main() {
   div_t d_t = make_div(1, 2);
}

[live demo]

OLD ANSWER:

If you are using c++17 you could also try to use structured binding, constexpr function and SFINAE overloading to detect which field is declared first in the structure:

#include <cstdlib>
#include <algorithm>
#include <iterator>

constexpr bool first_quot() {
    auto [x, y] = std::div_t{1, 0};
    (void)y;
    return x;
}

template <bool B = first_quot()>
std::enable_if_t<B, std::div_t> foo() {
    int quot = 1;
    int rem = 0;
    return {quot, rem};
}

template <bool B = first_quot()>
std::enable_if_t<!B, std::div_t> foo() {
    int quot = 1;
    int rem = 0;
    return {rem, quot};
}

int main() {
    foo();
}

[live demo]

Or even simpler use if constexpr:

#include <cstdlib>
#include <algorithm>
#include <iterator>

constexpr bool first_quot() {
    auto [x, y] = std::div_t{1, 0};
    (void)y;
    return x;
}

std::div_t foo() {
    int quot = 1;
    int rem = 0;
    if constexpr(first_quot())
        return {quot, rem};
    else
        return {rem, quot};
}

int main() {
    foo();
}

[live demo]

Community
  • 1
  • 1
W.F.
  • 13,888
  • 2
  • 34
  • 81
1

You can use a ternary to initialize this:

generate(rbegin(digits), rend(digits), [i = div_t{ 1, 0 }.quot ? div_t{ quot, 0 } : div_t{ 0, quot }]() mutable {
    i = div(i.quot, 10);
    return i.rem;
});

gcc6.3 for example will compile identical code with the ternary and without the ternary.

On the other hand clang3.9 compiles longer code with the ternary than it does without the ternary.

So whether the ternary is optimized out will vary between compilers. But in all cases it will give you implementation independent code that doesn't require a secondary function to be written.


Incidentally if you are into creating a helper function to create a div_t (or any of the other div returns) you can do it like this:

template <typename T>
enable_if_t<decltype(div(declval<T>(), declval<T>())){ 1, 0 }.quot != 0, decltype(div(declval<T>(), declval<T>()))> make_div(const T quot, const T rem) { return { quot, rem }; }
template <typename T>
enable_if_t<decltype(div(declval<T>(), declval<T>())){ 1, 0 }.quot == 0, decltype(div(declval<T>(), declval<T>()))> make_div(const T quot, const T rem) { return { rem, quot }; }

Note this does work on gcc but fails to compile on Visual Studio because of some non-conformity.

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • I failed to create workaround for now but haven't given up I'll try to do it later on – W.F. Jan 11 '17 at 17:21
  • @W.F. There are some pretty amazing answers going down over here: http://stackoverflow.com/q/41593649/2642059 My personal favorite is [Simon Kramer's](http://stackoverflow.com/a/41597153/2642059) because it doesn't add a defaulted template parameter that could be inadvertently hijacked. – Jonathan Mee Jan 11 '17 at 17:36
  • 1
    @JonathanMee Glad you liked my answer. Yet you shouldn't be worried about someone hijacking the other template parameters in Yakk's answer that's not possible. Especially since they aren't used and you also use `std::enable_if`. The `counter_types`, even if specified won't change anything when declared as he did. – Simon Kraemer Jan 11 '17 at 17:58
  • @SimonKraemer Interesting. I need to read up on all this stuff to understand it. Thanks. – Jonathan Mee Jan 11 '17 at 18:05
  • @JonathanMee maybe something like [this](http://rextester.com/GFMNR9147) would work? – W.F. Jan 11 '17 at 18:27
  • @W.F. A templatized variable or something like that does sound like a good idea as far as linking the two helper function options, but I'd sure like if it could cover all the potential `div` return structs. – Jonathan Mee Jan 11 '17 at 18:36
  • @JonathanMee this one constexpr variable? maybe you could test if the qual/rem is equal to given value provided by hand? – W.F. Jan 11 '17 at 18:43
  • @W.F. I'm not sure what you mean with "by hand" I want my code to be portable, so it needs to compile independent of implementation. – Jonathan Mee Jan 11 '17 at 18:52
  • @JonathanMee I thought about something like [this](http://rextester.com/NKZDG1702) (I really must work on my wording :) – W.F. Jan 11 '17 at 19:54
  • @W.F. Yeah that's what I thought you meant the first time. It does a good job of coupling the two functions. What I was talking about with templating is this: There are actually 4 different structs: `div_t`, `ldiv_t`, `lldiv_t`, and `imaxdiv_t` My functions handle all of those, creating the `div_t` variable requires us to declare a new pair for each variant. – Jonathan Mee Jan 11 '17 at 20:03
  • @JonathanMee I'll try to take it into account, but I got some error when using make_div this way :/ – W.F. Jan 11 '17 at 20:07
  • @W.F. Yeah that's functional, but now you're passing 2 variables to the template. You already know the struct from the type of integer passed in combination with `decltype(div(declval(), declval()))`. You can see that used in my answer. – Jonathan Mee Jan 11 '17 at 20:24
  • @W.F. Yeah but one more thing, you should be able to derive the struct type from the value passed in, you shouldn't have to specify it. So if my arguments are of type `int` then I want to make a `div_t` if my arguments are of type `long` then I want an `ldiv_t` and so on. – Jonathan Mee Jan 11 '17 at 20:46
  • @JonathanMee oh so you want to do this other way around :) I see... :) – W.F. Jan 11 '17 at 20:51
  • @W.F. Yeah so the goal if we're going to make a helper function would be to do something like this: `const auto myDiv = make_div(42L, 13L)` in which case `myDiv` would be a `ldiv_t`, with a `quot` of 42 and a `rem` of 13. – Jonathan Mee Jan 11 '17 at 20:55
  • @W.F. Yeah that's it, if you update your answer I will accept. – Jonathan Mee Jan 11 '17 at 21:06
1

My solution uses a constexpr function that itself wraps and executes a lambda function that determines and initializes the correct div_t depending on the template parameters.

template <typename T>
constexpr auto make_div(const T quot, const T rem)
{
    return [&]() {
        decltype(std::div(quot, rem)) result;
        result.quot = quot;
        result.rem = rem;
        return result;
    }();
}

This works with MSVC15, gcc 6.3 and clang 3.9.1.

http://rextester.com/AOBCH32388


The lambda allows us to initialize a value step by step within a constexpr function. So we can set quot and rem correctly and independently from the order they appear in the datatype itself.

By wrapping it into a constexpr function we allow the compiler to completely optimize the call to make_div:

clang: https://godbolt.org/g/YdZGkX

gcc: https://godbolt.org/g/sA61LK

Simon Kraemer
  • 5,700
  • 1
  • 19
  • 49
  • I'm assuming that the wrapped lambda allows us to compile in Visual Studio? otherwise you would have presumably done: `decltype(div(declval(), declval())) make_div(const T quot, const T rem)` – Jonathan Mee Jan 12 '17 at 15:35
  • @JonathanMee I don't get what you are trying to tell me. `make_div` uses auto because I want the type to depend on the return value of the lambda and the lambda uses auto (not visible) because I want the return type not all over the place. There is no point in calling `decltype` multiple times. The lambda is only there because you can't create uninitialized variables inside constexpr functions directly. This solution goes a totally different way and doesn't have the SFINAE problems. – Simon Kraemer Jan 12 '17 at 15:45
  • What I'm trying to communicate is the lambda should be unnecessary: http://ideone.com/0yTqWP I'm assuming you're using it to compile in Visual Studio 2015? – Jonathan Mee Jan 12 '17 at 16:07
  • Hmm, that kind of looks wrong to me as _"the function body must be either deleted or defaulted or contain any statements except - a definition of a variable of non-literal type"_ (http://en.cppreference.com/w/cpp/language/constexpr). Maybe you should open up another question asking which version is correct according to the standard. – Simon Kraemer Jan 12 '17 at 16:12
  • I've asked a new question here: http://stackoverflow.com/q/41618576/2642059 But I think that [literal types](http://en.cppreference.com/w/cpp/concept/LiteralType) are pretty encompassing. So I expect that the lambda should not be required and Visual Studio is just wrong again. – Jonathan Mee Jan 12 '17 at 16:48
  • @cpplearner mentions in the other thread that the result of `make_div` can't seem to be assigned to a `constexpr` variable. I'm not sure if something's not supported or what. – Jonathan Mee Jan 12 '17 at 19:03
  • So the lambda seems to be C++17 code I'm not certain why it compiles on gcc and Visual Studio. In any case rolling the ternary from my answer in with this answer should allow a C++11 compliant `constexpr` function. See my answer here: http://stackoverflow.com/a/41636213/2642059 – Jonathan Mee Jan 13 '17 at 14:00