有没有保证 sizeof(which) > 1 的简单类型?

问题描述

在编写通用代码时,我经常需要一个简单的类型 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";
}