问题描述
在编写通用代码时,我经常需要一个简单的类型 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> {};
-
long long
:不起作用,参见 here -
struct SizeNot1 { char dummy[2]; };
:必须提前定义,有点烦 -
char (&test_foo())[2];
:太丑了 -
std::array<char,2>
:它的大小有保证吗?
有什么想法吗?
解决方法
在编写通用代码时,我经常需要一个简单的类型 T
,保证 sizeof(T) > 1
。
我认为你的做法“错误”。
对于您的示例,您可以直接使用 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,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];
:太丑了
有更好的替代语法:
auto test_foo() -> char(&)[2];
但使用 typedef 会更易读 IMO:
template <std::size_t N>
using c_char_array = char[N];
然后
c_char_array<2>& test_foo();
,
我突然想到这应该可行:
std::aligned_storage_t<2> & test_foo(int);
这不会引入新名称,并且具有相当的可读性。
,从 sizeof(char) == 1
开始,您可以使用 char[2]
。正如您所提到的,其语法是
char (&test_foo())[2];
这可行,但可能有点难以阅读。
这是一个主观的答案,但我认为
decltype(" ") test_foo();
相当可读。这里我们只使用 char[2]
类型的文字类型。
以防万一。如果您尝试执行检测功能存在的模板,则可以这样做:
#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";
}