写一个仅接受文字“ 0”或文字“ 1”作为参数的函数

问题描述 投票:2回答:1

有时对于代数类型,使用构造函数使用文字值0表示中性元素,或使用1表示乘法恒等元素很方便,即使基础类型不是整数。

问题是,如何说服编译器仅接受01而不接受任何other整数并不明显。

在C ++ 14或更高版本中是否有办法做到这一点,例如结合文字,constexpr或static_assert?

让我用一个自由函数来说明(尽管这个想法是对采用单个参数的构造函数使用该技术。构造函数也不能采用模板参数)。

仅接受零的函数可以这样编写:

constexpr void f_zero(int zero){assert(zero==0); ...}

问题是,这只能在运行时失败。我可以写f_zero(2)甚至f_zero(2.2),程序仍然可以编译。

第二种情况很容易删除,例如通过使用enable_if

template<class Int, typename = std::enable_if_t<std::is_same<Int, int>{}> >
constexpr void g_zero(Int zero){assert(zero==0);}

这仍然存在我可以传递任何整数的问题(并且它仅在调试模式下失败)。

在C ++ pre 11中,有能力做到这一点,只接受文字零。

struct zero_tag_{}; 
using zero_t = zero_tag_***;
constexpr void h_zero(zero_t zero){assert(zero==nullptr);}

这实际上允许在那里保留99%,但非常难看的错误消息除外。因为,基本上(模Maquevelian用法),唯一接受的参数是h_zero(0)

[这是事态在这里https://godbolt.org/z/wSD9ri所示。我看到了Boost.Units库中正在使用的这项技术。

1)现在可以使用C ++的新功能做得更好吗?

我问的原因是因为使用文字1时上述技术完全失败。

2] 是否有等效的技巧可以应用于文字1的情况?(理想情况下,作为单独的函数)。

我可以想象,可以发明一个非标准的长整型文字_c,该文字创建std::integral_constant<int, 0>std::integral_constant<int, 1>的实例,然后使函数采用这些类型。但是,对于0情况,结果语法将最差。也许有些简单。

f(0_c);
f(1_c);

EDIT:我应该提到,由于f(0)f(1)可能是完全独立的函数,因此理想情况下它们应该调用不同的函数(或重载)。

c++ c++11 c++17 constexpr literals
1个回答
1
投票

您可以通过将0或1作为模板参数来传递,如下所示:

template <int value, typename = std::enable_if_t<value == 0 | value == 1>>
void f() {
    // Do something with value
}

然后将调用该函数,例如:f<0>()。我不相信构造函数可以做同样的事情(因为您不能为构造函数显式设置模板参数),但是您可以将构造函数设为私有并具有静态包装函数,可以给模板参数执行检查:

class A {
private:
    A(int value) { ... }

public:
    template <int value, typename = std::enable_if_t<value == 0 || value == 1>>
    static A make_A() {
        return A(value);
    }
};

A类型的对象将用A::make_A<0>()创建。

© www.soinside.com 2019 - 2024. All rights reserved.