0
votes

I'm trying to use https://github.com/gdelugre/literal_ipaddr which says it is a

C++17 constexpr implementation of inet_addr / inet_aton / inet_pton

When I do:

auto ipSourceAddressTest = IPAddr::inet_pton<AF_INET>("127.0.0.1");
std::cout << "ipSourceAddressTest is " << ipSourceAddressTest.s_addr << std::endl;

This works fine. I get the IP address in decimal.

However:

std::string ipv4address;
//get ipv4address from world here
const unsigned int ipMaxSize = 200;
char ip[ipMaxSize];
std::copy(ipv4address.begin(), ipv4address.end(), ip);
auto ipSourceAddress = IPAddr::inet_pton<AF_INET>(ip);
std::cout << "ipSourceAddress is " << ipSourceAddress.s_addr << std::endl;

Remember that ipSourceAddress.s_addr is uint32_t. The value I get printed is not the IP in decimal but in fact is 4294967295 which is 111...111 in binary. So I think it is getting its value at compile time rather than runtime.

If I do

constexpr auto in_addr1 = IPAddr::inet_pton<AF_INET>(ip);

then it's understandable that its value will be deduces in compile time. But I didn't use constexpr in my variable declaration. Does auto implies constexpr?

According to https://en.cppreference.com/w/cpp/language/constexpr,

A constexpr specifier used in a function or static member variable (since C++17) declaration implies inline

so why the function inet_pton is getting its value in compile time?

1
How do you know, that it is computed at compile time? Did you look at generated assembly? Note: Your ip array is uninitialized (because ipv4address is empty, and std::copy does nothing, due to that), hence using it, is undefined behavior. - Algirdas Preidžius
A constexpr function can be called at runtime. It's only calculated at compile-time if possible. - super
@AlgirdasPreidžius ipv4address is not empty, in the comment I am getting it from the world. - Guerlando OCs
@GuerlandoOCs "ipv4address is not empty, in the comment I am getting it from the world." Then, please provide minimal reproducible example. More on that: is ip being treated as null-terminated string (C-string) in IPAddr::inet_pton<AF_INET>(ip);? If so, it's undefined behavior, even if ipv4address is not empty, since std::copy wouldn't copy the null-terminator. - Algirdas Preidžius
@KaenbyouRin Looking at the library, it seems to be meant primarily for compile-time use and accepts only char arrays, not pointers. - walnut

1 Answers

3
votes

ipSourceAddress does not get its value at compile time (as-if rule nonwithstanding).

ip's value is not usable in a constant expression since it is not declared constexpr and doesn't qualify for one of the other exceptions to the rule of lvalue-to-rvalue conversion in a constant expression. Therefore IPAddr::inet_pton<AF_INET>(ip) is not a constant expression.

You can see this clearly by making ipSourceAddress constexpr (which auto does not imply).

constexpr on a variable requires initialization at compile-time and because the initializer is not a constant expression it will fail.

See godbolt.

I don't know how you come to a different conclusion.


Note however that the library does seem to require that the char array passed to it is exactly as long as the string it contains (plus null-terminator). It fails if you hand it a longer array and outputs the value you are seeing.

See godbolt.

It seems the author intends the functions to only be called directly with string literals.