Can the following function template be made to actually act based on argument type :
#include <iostream>
#include <memory>
#include <tuple>
#include <typeinfo>
using namespace std;
using UPSTR = unique_ptr<char[]>;
template<typename... Ts>
void uprint(Ts const&... strs){
auto tp = std::tie(strs...);
auto& x = std::get<0>(tp);
if(typeid(x)==typeid(UPSTR)) cout << x.get() << endl;
// Error : no match for 'operator<<' and 'const std::unique_ptr<char []>') :
else cout << x << endl;
}
int main(){
UPSTR str = make_unique<char[]>(10); str.get()[0] = 'A';
uprint(str, "hello");
return 0;
}
?
Error from gcc 12.2 : no match for 'operator<<' and 'const std::unique_ptr<char []>')
https://godbolt.org/z/dYG9r7Koj (MSVC does compile this !)
CodePudding user response:
The compiler always instantiates the whole body of a function template, no matter whether some if
statements can be proven at compile-time to be false. So any syntax/type errors, even in false branches are reported.
But exactly for this use case, there is if constexpr
:
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, UPSTR>)
cout << x.get() << endl;
else
cout << x << endl;
typeid
is not compile-time construct,decltype
is.std::decay_t
removes references constness -> easier matching.
Note that since C 20, std::unique_ptr
got its operator<<
which prints its underlying value exactly through os << x.get()
so cout<<x;
becomes always valid.
CodePudding user response:
Simply create a helper function with overloads and let overload resolution take care of producing this logic for you. This is much easier to extend and adds logic that can be reused much easier than if
.
template<class T>
void Print(T const& value)
{
std::cout << value;
}
inline void Print(std::unique_ptr<char[]> const& value)
{
std::cout << value.get();
}
template<typename... Ts>
void uprint(Ts const&... strs) {
auto tp = std::tie(strs...);
auto& x = std::get<0>(tp);
Print(x);
std::cout << std::endl;
}
int main() {
auto str = std::make_unique<char[]>(10); str[0] = 'A';
uprint(str, "hello");
return 0;
}