Home > Back-end >  Is there a way to make function not type-checked in C ?
Is there a way to make function not type-checked in C ?

Time:09-10

I am currently implementing a class that is a three-way map, meaning each "index" has three keys and one can retrieve each. The function get is defined as:

template<typename returnType, typename getType>
returnType get(getType getVal) {
    if (typeid(returnType) == typeid(getType)) {
        return getVal;
    }
    
    // Here the appropriate value is gotten. Not important for this.
    
    // This is returned just in-case nothing is found.
    return *new returnType;
}

This doesn't compile, because getType is not always equal to returnType, which is guaranteed by my check. Is there a way to make this compile, because the getting process is quite expensive. I've tried to just do return returnType(getVal);, which only works if returnType has a constructor for getType.

Solutions I could imagine but didn't manage to pull of:

  • template specialization
  • disable type-checking (similar to rust's unsafe)

P.S: I know this optimisation doesn't make a lot of sense, still would like to know if it's possible to compile.

CodePudding user response:

typeid is not meant to be used this way at compile-time. If you want to operate on types at compile-time, use the tools from #include<type_traits>. typeid is meant to be used if you need to operate on types at runtime (e.g. store ids for types in a container or obtain a printable name for a type) or you need to determine the actual type of a polymorphic pointer/lvalue at runtime.

To compare types at compile-time use std::is_same_v<returnType, getType>. Since C 17 it is also possible to conditionally compile branches of an if in a template, using if constexpr instead of if:

template<typename returnType, typename getType>
returnType get(getType getVal) {
    if constexpr (std::is_same_v<returnType, getType>) {
        return getVal;
    } else {
        // Here the appropriate value is gotten. Not important for this.
    
        // This is returned just in-case nothing is found.
        return /*some returnType*/;
    }
}

Also note that applying * to a new expression is practically always wrong. You are returning *new returnType immediately by-value. That is a guaranteed immediate memory leak. new returns a pointer to newly allocated memory with a new object of the given type in it. Returning the dereferenced pointer by-value means that this new object is again copied into the return value and at the same time the lvalue/pointer to the first newly created object is lost in the copy/move constructor.

To create an object to return directly, do not use new. Just return a temporary object using the functional explicit cast notation:

return returnType{};

or even shorter, since returnType is already mentioned in the function return type:

return {};

new is very rarely needed directly in C . If a variable or a temporary as above also works, then don't use new, and if that doesn't work reconsider whether you shouldn't be using std::unique_ptr/std::shared_ptr/std::vector/std::string/etc. instead of new.

  • Related