如何检查类型具有constexpr构造函数

发布于 2025-01-23 03:09:58 字数 810 浏览 0 评论 0原文

我希望我的班级使用其他实现类型没有ConstexPR构造函数。

这样:

template <typename A>
class foo
{
public:

    // if A has constexpr constructor
    constexpr foo() :_flag(true) { _data._a = A(); }
    // else
    constexpr foo() : _flag(false) { _data.x = 0; }

    ~foo(){}

    bool _flag;
    union _data_t
    {
        _data_t() {} // nothing, because it's just an example
        ~_data_t() {}
        A _a;
        int x;
    }_data;
};

为了实现标题所说的内容,我尝试了:

template<typename _t, _t = _t()>
constexpr bool f()
{
    return true;
}
template<typename _t>
constexpr bool f()
{
    return false;
}

它适用于不constexpr构造函数的类型。 但是对于其他类型,它会导致含糊不清的超负荷的编译错误。

那我该如何检查呢?

I want my class use another implementation for types don't have constexpr constructor.

like this:

template <typename A>
class foo
{
public:

    // if A has constexpr constructor
    constexpr foo() :_flag(true) { _data._a = A(); }
    // else
    constexpr foo() : _flag(false) { _data.x = 0; }

    ~foo(){}

    bool _flag;
    union _data_t
    {
        _data_t() {} // nothing, because it's just an example
        ~_data_t() {}
        A _a;
        int x;
    }_data;
};

To achieve what the title says, I try this:

template<typename _t, _t = _t()>
constexpr bool f()
{
    return true;
}
template<typename _t>
constexpr bool f()
{
    return false;
}

It works well for types haven't constexpr constructor.
But for other types it causes a compile error with ambiguous overloads.

so how can I check?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

原谅过去的我 2025-01-30 03:09:58

将Sfinae与逗号运算符的功能一起使用

我想您可以在想法之后

template <typename T, int = (T{}, 0)>
constexpr bool f (int)
{ return true; }

template <typename>
constexpr bool f (long)
{ return false; }

,您可以将f()函数重写如下。 )对于第二个模板参数,

f()才能在t {}可以构造时才启用(逗号运算符的功率)(因为代码>(t {},0)是模板参数的参数),否则Sfinae擦除了f()的第一个版本

并观察到f()的拳头版本接收未使用的int,其中第二个接收long。这样,第一个版本是首选的,如果可用,请使用int来调用f();当第一个不可用时,选择第二个总比没有解决方案要好(当第一个模板参数不是constexpr默认构造时)。

现在,您可以根据foo构建两个模板构造函数或不是constexpr构造的

template <typename T = A,
          std::enable_if_t<f<T>(0), std::nullptr_t> = nullptr>
constexpr foo() { std::cout << "constexpr" << std::endl; }

template <typename T = A,
          std::enable_if_t<not f<T>(0), std::nullptr_t> = nullptr>
constexpr foo() { std::cout << "not constexpr" << std::endl; }

以下是一个完整的编译示例(C ++ 14或更新,但您可以为C ++ 11进行修改):

#include <iostream>
#include <type_traits>

template <typename T, int = (T{}, 0)>
constexpr bool f (int)
{ return true; }

template <typename>
constexpr bool f (long)
{ return false; }

template <typename A>
struct foo
{
  template <typename T = A,
            std::enable_if_t<f<T>(0), std::nullptr_t> = nullptr>
  constexpr foo() { std::cout << "constexpr" << std::endl; }

  template <typename T = A,
            std::enable_if_t<not f<T>(0), std::nullptr_t> = nullptr>
  constexpr foo() { std::cout << "not constexpr" << std::endl; }
};


struct X1 { constexpr X1 () {} };
struct X2 {           X2 () {} };


int main()
{
  foo<X1> f1;  // print "constexpr"
  foo<X2> f2;  // print "not constexpr"
}

I suppose you can use SFINAE together with the power of the comma operator

Following your idea, you can rewrite your f() functions as follows

template <typename T, int = (T{}, 0)>
constexpr bool f (int)
{ return true; }

template <typename>
constexpr bool f (long)
{ return false; }

Observe the trick: int = (T{}, 0) for the second template argument

This way f() is enabled (power of the comma operator) only if T{} can be constexpr constructed (because (T{}, 0) is the argument for a template parameter), otherwise SFINAE wipe away the first version of f().

And observe that the fist version of f() receive an unused int where the second one receive a long. This way the first version is preferred, when available, calling f() with an int; the second one is selected, as better than nothing solution, when the first one is unavailable (when the first template argument isn't constexpr default constructible).

Now you can construct two template constructors for foo that you can alternatively enable/disable according the fact the template parameter T (defaulted to A) is or isn't constexpr constructible

template <typename T = A,
          std::enable_if_t<f<T>(0), std::nullptr_t> = nullptr>
constexpr foo() { std::cout << "constexpr" << std::endl; }

template <typename T = A,
          std::enable_if_t<not f<T>(0), std::nullptr_t> = nullptr>
constexpr foo() { std::cout << "not constexpr" << std::endl; }

The following is a full compiling example (C++14 or newer, but you can modify it for C++11):

#include <iostream>
#include <type_traits>

template <typename T, int = (T{}, 0)>
constexpr bool f (int)
{ return true; }

template <typename>
constexpr bool f (long)
{ return false; }

template <typename A>
struct foo
{
  template <typename T = A,
            std::enable_if_t<f<T>(0), std::nullptr_t> = nullptr>
  constexpr foo() { std::cout << "constexpr" << std::endl; }

  template <typename T = A,
            std::enable_if_t<not f<T>(0), std::nullptr_t> = nullptr>
  constexpr foo() { std::cout << "not constexpr" << std::endl; }
};


struct X1 { constexpr X1 () {} };
struct X2 {           X2 () {} };


int main()
{
  foo<X1> f1;  // print "constexpr"
  foo<X2> f2;  // print "not constexpr"
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文