Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid implicit conversions from integer 0 to pointer, as the element of a vector

There is a situation where I want to collect all the nodes names of a path to one key in JSON. Consider the condition: JSON array index "0", "1" are also allowed, but it is easy to forget the quotes, which would lead to a crash when doing dereference. So I want compiler to reject this kind of parameters. Example:

#include <vector>
#include <iostream>

int func(const std::vector<const char*>& pin) {
    return pin.size();
}

int main() {
    // {"aname", "3", "path", "0"} wanted but this still compile
    std::cout << func({"aname", "3", "path", 0}) << std::endl;
}

Refering to How do I avoid implicit conversions on non-constructing functions? I tried something as following:

#include <vector>
#include <iostream>

// I want to describe only char pointer parameter is allowed as element,
// parameter of any integer types should be rejected.
int func(const std::vector<const char*>& pin) {
    return pin.size();
}

int func(const std::vector<int>& pin) = delete;
// or
template<typename T>
int func(const std::vector<T>& pin) = delete;

int main() {
    std::cout << func({"aname", "3", "path", 0}) << std::endl;
}

But the compiler still can not understand me.
Any suggestion?

Please point out any misuse of terminologies and assumptions, thank you!

like image 381
rustyhu Avatar asked Apr 16 '20 05:04

rustyhu


People also ask

What types can int be implicitly converted to?

Implicit numeric conversions Any integral numeric type is implicitly convertible to any floating-point numeric type.

Is implicit type conversion bad?

Implicit conversions allow the compiler to treat values of a type as values of another type. There's at least one set of scenarios in which this is unambiguously bad: non-total conversions. That is, converting an A to a B when there exists A s for which this conversion is impossible.

What is implicit type of conversion?

Overview. Implicit type conversion in C language is the conversion of one data type into another datatype by the compiler during the execution of the program. It is also called automatic type conversion.

What is an implicit type conversion in C++?

Implicit type conversion also known as automatic type conversion is carried out by the compiler without the need for a user-initiated action. It takes place when an expression of more than one data type is present which in such an instance type conversion takes place to avoid data loss.


2 Answers

Something like this? It's very similar to the overload solution you suggested, but requires wrapping the vector type. Fails to build if you provide a literal 0 because the deleted constructor overload is chosen.

#include <memory>
#include <new>
#include <vector>
#include <iostream>
using std::vector;

template<typename T>
struct no_zero {
        no_zero(T val) : val(val) {}
        no_zero(int val) = delete;
        operator T() { return val; }
        T val;
};

int func(const vector<no_zero<const char*> >& pin) {
    return pin.size();
}

int main() {
    // {"aname", "3", "path", "0"} wanted but this still compile
    std::cout << func({"aname", "3", "path", 0}) << std::endl;
}
like image 129
Mikel Rychliski Avatar answered Nov 11 '22 07:11

Mikel Rychliski


I like Mikel Rychliski's answer. However there already exists a solution in Guideline Support Library:

gsl::not_null

I highly recommend GSL. It's created and backed by many C++ experts, Bjarne Stroustrup himself and Herb Sutter among them. And the C++ Core Guidelines are actively being integrated into the compiler warnings and static analyzers.

like image 29
bolov Avatar answered Nov 11 '22 05:11

bolov