gpt4 book ai didi

c++ - 区分用户类型和原语

转载 作者:行者123 更新时间:2023-11-30 04:44:27 25 4
gpt4 key购买 nike

我试图在可变参数模板中区分用户类型和原始类型。

我试过重载二元运算符,但这只是说“用户类型”没有合适的重载...

template <typename T>
void PrintParams(T t)
{
if (IsAUserType)
std::cout << typeid(t).name();
else
std::cout << t;
}

template <typename First, typename... Rest>
void PrintParams(First first, Rest... rest)
{
if (IsAUserType)
std::cout << typeid(first).name();
else
std::cout << first;

PrintParams(rest...);
}

// If you know what to do with this, then that would also be very helpful...
//Overload << operator for user types
//template <typename T>
//friend std::ostream& operator<< (std::ostream& os, T t)
//{
//
//if (std::is_fundamental<t>::value)
//std::clog << t;
//else
//std::clog << typeid(t).name();
//}

输入(类测试,3.4,“字符串”)的预期结果将是“test3.4字符串”

最佳答案

您可以将单个参数函数一分为二,然后使用 SFINAE 根据参数是否为基本类型来启用正确的函数:

template<typename T, typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0>
void PrintParams(T t) {
std::cout << t;
}

template<typename T, typename std::enable_if<!std::is_fundamental<T>::value, int>::type = 0>
void PrintParams(T t) {
std::cout << typeid(t).name();
}

template<typename First, typename... Rest>
void PrintParams(First first, Rest... rest) {
PrintParams(first); // ... and call the single argument version here
std::cout << ",";
PrintParams(rest...);
}

另一种方法是使用 operator<< 检查类型是否支持流式传输而不是检查它是否是基本类型。这将使流式处理适用于类(如 std::string 和用户定义的类)。

#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <utility>
// SFINAE support

namespace detail {
template<class>
struct sfinae_true : std::true_type {};

template<class S, class T>
static auto test_lshift(int)
-> sfinae_true<decltype(std::declval<S>() << std::declval<T>())>;

template<class S, class T>
static auto test_lshift(long) -> std::false_type;
} // namespace detail

template<class T>
struct has_ostream : decltype(detail::test_lshift<std::ostream, T>(0)) {};
// using the SFINAE support stuff

template<typename T, typename std::enable_if<has_ostream<T>::value, int>::type = 0>
void PrintParams(const T& t) {
std::cout << "Type: " << typeid(t).name() << "\n"
<< " supports operator<< Value = " << t << "\n";
}

template<typename T, typename std::enable_if<!has_ostream<T>::value, int>::type = 0>
void PrintParams(const T& t) {
std::cout << "Type: " << typeid(t).name() << "\n"
<< " does NOT support operator<<\n";
}

template<typename First, typename... Rest>
void PrintParams(First first, Rest... rest) {
PrintParams(first);
PrintParams(rest...);
}
// example classes

class Foo { // will not support streaming
int x = 5;
};

class Bar { // this should support streaming
int x = 10;
friend std::ostream& operator<<(std::ostream&, const Bar&);
};

std::ostream& operator<<(std::ostream& os, const Bar& b) {
return os << b.x;
}
// testing

int main() {
int i = 2;
Foo f;
Bar b;
std::string s = "Hello world";

PrintParams(i, f, b, s);
}

可能的输出:

Type: i
supports operator<< Value = 2
Type: 3Foo
does NOT support operator<<
Type: 3Bar
supports operator<< Value = 10
Type: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
supports operator<< Value = Hello world

关于c++ - 区分用户类型和原语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57746801/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com