I have a function to determine whether a template type is pointer.
template<class T>
struct is_pointer_struct { static const bool value = false; };
template<class T>
struct is_pointer_struct<T*> { static const bool value = true; };
template<class T>
bool is_pointer(T &var) {
return is_pointer_struct<T>::value;
}
And I have a initialize function.
template<class T>
void initialize(T &val) {
if (is_pointer(val))
val = NULL;
else
val = T();
}
Obviously, when T
is string
, this code can't be compiled. Is there a way that compile val = NULL
when T
is pointer type and compile val = T()
when T
is not a pointer type?
All the template parameters are fixed+known at compile-time. If there are compiler errors due to template instantiation, they must be caught at compile-time!
The template function must be inline and visible, typically this is all done in the header file. You wouldn't normally place the code in a . cpp file to be compiled as a separate module.
The compiler usually instantiates members of template classes independently of other members, so that the compiler instantiates only members that are used within the program. Methods written solely for use through a debugger will therefore not normally be instantiated.
The template repository stores template instances between separate compilations so that template instances are compiled only when necessary. The template repository contains all nonsource files needed for template instantiation when using the external instances method.
In your particular case you could just use uniform initialization, as VTT said:
val = T{};
Also, the Standard Library provides std::is_pointer
.
As an answer to the more general question "how do I branch at compile-time?":
In C++17, all you have to do is change your if(...)
to if constexpr(...)
:
template<class T>
void initialize(T &val) {
if constexpr(is_pointer(val))
val = nullptr;
else
val = T();
}
In C++14, you can implement your own static_if
.
In C++03/11, you could use tag dispatching:
template <typename T>
void initialize_impl(std::true_type /* pointer */, T& val)
{
val = NULL;
}
template <typename T>
void initialize_impl(std::false_type /* non-pointer */, T& val)
{
val = T();
}
template<class T>
void initialize(T &val) { initialize_impl(std::is_pointer<T>{}, val); }
The right way to do the things in your case is to use uniform initialization, as it is mentioned.
As an option, you might make use of SFINAE based on your type trait so the necessary template will be instantiated (here is a C++ 11 way to do that):
template<class T>
auto initialize(T &val) ->
typename std::enable_if<is_pointer_struct<T>::value>::type {
val = nullptr;
}
template<class T>
auto initialize(T &val) ->
typename std::enable_if<!is_pointer_struct<T>::value>::type {
val = T();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With