是否有任何简单类型 sizeof(which) > 1 是有保证的?
Are there any simple types sizeof(which) > 1 is guaranteed?
在编写泛型代码时,我经常想要一个简单类型 T
,保证 sizeof(T) > 1
。
例如:
template <typename T>
char test_foo(...);
template <typename T,
typename = std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::foo)>>>
??? test_foo(int);
template <typename T>
struct has_foo : std::bool_constant<sizeof(test_foo<T>(0))!=1> {};
我有几个选择,但 none 是最理想的:
long long
:不起作用,参见here
struct SizeNot1 { char dummy[2]; };
: 得提前定义,有点烦人
char (&test_foo())[2];
: 太丑了
std::array<char, 2>
:大小有保证吗?
有什么想法吗?
从 sizeof(char) == 1
开始,您可以使用 char[2]
。正如您所提到的,语法是
char (&test_foo())[2];
有效,但可能有点难以阅读。
这是一个主观的答案,但我认为
decltype(" ") test_foo();
相当可读。这里我们只使用 char[2]
.
类型的文字类型
我突然想到这应该行得通:
std::aligned_storage_t<2> & test_foo(int);
这没有引入新名称,而且可读性很好。
When writing generic code, I often want a simple type T
for which sizeof(T) > 1
is guaranteed.
我认为你这样做的方式“错误”。
对于你的例子,你可以直接使用std::true_type
/std::false_type
。
template <typename>
std::false_type test_foo(...);
template <typename T, std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::foo)>, int> = 0>
std::true_type test_foo(int);
template <typename T>
using has_foo = deltype(test_foo<T>(0));
如果您需要不同的 compile_time 类型内的数字,std::integral_constant
可能会有所帮助:
template <typename>
std::integral_constant<std::size_t, 0> test_foo(...);
template <typename T, std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::foo)>, int> = 0>
std::integral_constant<std::size_t, 42> test_foo(int);
template <typename T>
using has_foo = std::bool_constant<deltype(test_foo<T>(0))() == 42>;
char (&test_foo())[2];
: too ugly
有更好的替代语法:
auto test_foo() -> char(&)[2];
但使用 typedef 会更具可读性 IMO:
template <std::size_t N>
using c_char_array = char[N];
然后
c_char_array<2>& test_foo();
以防万一。如果您尝试做检测功能存在的模板,这是如何完成的:
#include <iostream>
#include <type_traits>
class A {
public:
int func() {return 1;}
};
class B {
};
template <typename T, typename = void>
struct has_func : std::false_type {};
template <typename T>
struct has_func<T, std::void_t<decltype(std::declval<T>().func())>>
: std::true_type {};
template<typename T>
int wrap(T &t) {
if constexpr (has_func<T>::value) {
return t.func();
} else {
return 0;
}
}
int main()
{
A a;
B b;
std::cout << "A:" << wrap(a) << ", B:" << wrap(b) << "\n";
}
在编写泛型代码时,我经常想要一个简单类型 T
,保证 sizeof(T) > 1
。
例如:
template <typename T>
char test_foo(...);
template <typename T,
typename = std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::foo)>>>
??? test_foo(int);
template <typename T>
struct has_foo : std::bool_constant<sizeof(test_foo<T>(0))!=1> {};
我有几个选择,但 none 是最理想的:
long long
:不起作用,参见herestruct SizeNot1 { char dummy[2]; };
: 得提前定义,有点烦人char (&test_foo())[2];
: 太丑了std::array<char, 2>
:大小有保证吗?
有什么想法吗?
从 sizeof(char) == 1
开始,您可以使用 char[2]
。正如您所提到的,语法是
char (&test_foo())[2];
有效,但可能有点难以阅读。
这是一个主观的答案,但我认为
decltype(" ") test_foo();
相当可读。这里我们只使用 char[2]
.
我突然想到这应该行得通:
std::aligned_storage_t<2> & test_foo(int);
这没有引入新名称,而且可读性很好。
When writing generic code, I often want a simple type
T
for whichsizeof(T) > 1
is guaranteed.
我认为你这样做的方式“错误”。
对于你的例子,你可以直接使用std::true_type
/std::false_type
。
template <typename>
std::false_type test_foo(...);
template <typename T, std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::foo)>, int> = 0>
std::true_type test_foo(int);
template <typename T>
using has_foo = deltype(test_foo<T>(0));
如果您需要不同的 compile_time 类型内的数字,std::integral_constant
可能会有所帮助:
template <typename>
std::integral_constant<std::size_t, 0> test_foo(...);
template <typename T, std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::foo)>, int> = 0>
std::integral_constant<std::size_t, 42> test_foo(int);
template <typename T>
using has_foo = std::bool_constant<deltype(test_foo<T>(0))() == 42>;
char (&test_foo())[2];
: too ugly
有更好的替代语法:
auto test_foo() -> char(&)[2];
但使用 typedef 会更具可读性 IMO:
template <std::size_t N>
using c_char_array = char[N];
然后
c_char_array<2>& test_foo();
以防万一。如果您尝试做检测功能存在的模板,这是如何完成的:
#include <iostream>
#include <type_traits>
class A {
public:
int func() {return 1;}
};
class B {
};
template <typename T, typename = void>
struct has_func : std::false_type {};
template <typename T>
struct has_func<T, std::void_t<decltype(std::declval<T>().func())>>
: std::true_type {};
template<typename T>
int wrap(T &t) {
if constexpr (has_func<T>::value) {
return t.func();
} else {
return 0;
}
}
int main()
{
A a;
B b;
std::cout << "A:" << wrap(a) << ", B:" << wrap(b) << "\n";
}