C++ 有没有办法从“std::initializer\u list”创建用户定义的文本?

C++ 有没有办法从“std::initializer\u list”创建用户定义的文本?,c++,literals,initializer-list,c++17,C++,Literals,Initializer List,C++17,就像在主题中一样:有没有一种方法可以从std::initializer_list创建用户定义的文本 我正在尝试做这样的事情: template <typename T> inline std::initializer_list<T> const & operator "" _lit(std::initializer_list<T> const & list) { return std::move(list); // I am not s

就像在主题中一样:有没有一种方法可以从
std::initializer_list
创建用户定义的文本

我正在尝试做这样的事情:

template <typename T> inline
std::initializer_list<T> const & operator "" _lit(std::initializer_list<T> const & list)
{
    return std::move(list); // I am not sure, but this line might cause undefined behavior... well I'll think about it latter...
}

int main()
{
    { 10, 20, 30, 40 }_lit // Error: identifier '_lit' is undefined;

    return 0;
}
沿着这条路线:

if (std::initializer_list<T>{val_1, val_2, val_3} == value)
if(std::initializer_list{val_1,val_2,val_3}==value)
ofc我提供了一个额外的操作员:

template <typename T> inline
bool operator==(std::initializer_list<T> const & list, T const & ref)
{
    for (auto const & element : list)
    {
        if (element == ref) { /* Do nothing. */ }
        else
        {
            return false;
        }
    }
    return true;
}
模板内联
布尔运算符==(std::初始值设定项\u list const&list,T const&ref)
{
用于(自动常量和元素:列表)
{
如果(element==ref){/*什么都不做。*/}
其他的
{
返回false;
}
}
返回true;
}
一切都会很好,但我不喜欢在花括号前键入
std::initializer\u list
。。。否则,编译器将选择默认版本的
运算符==()
,我将得到一个编译错误


文字在这里是为了将
if(std::initializer\u list{val\u 1,val\u 2,val\u 3}==value)
更改为
if({val\u 1,val\u 2,val\u 3}=value)
您不能为
std::initializer\u list
创建用户定义的文字。幸运的是,虽然C++17提供了一个新的非常酷的工具,将帮助我们。允许我们只使用类模板的名称,编译器将计算出模板参数需要是什么,这样我们就不必指定它们。这意味着您可以利用
std::array
,您的代码将

template<typename T, std::size_t N>
bool operator==(std::array<T, N> const & list, T const & ref)
{
    for(auto const& e : list)
        if (e != ref)
            return false;
    return true;
}

int main()
{
    using std::array;
    if (array{4,4,4,4,4} == 4)
        std::cout << "all 4";
}
模板
布尔运算符==(标准::数组常量和列表,T常量和参考)
{
用于(自动施工和设备:列表)
如果(e!=ref)
返回false;
返回true;
}
int main()
{
使用std::数组;
if(数组{4,4,4,4}==4)
标准::cout来自评论:

我试图“扩展”当前C++语法(这是一种乐趣) 小项目…)主要思想是简化这个:if((val_1== value)和&(val_2==value)和&(val_3==value))转换为:如果 (std::初始值设定项_列表{val_1,val_2,val_3}==值)(带有 重载运算符:bool运算符==(std::初始值设定项\u list const& list,T const&ref))…我想编辑我需要的部分 输入std::initializer\u list,我发现我可以更改它 转换为自定义文字

看起来你需要这样的东西:

template<typename T>
bool allEqualTo(T a, T b)
{
    return a == b;
}

template<typename T, typename... TArgs>
bool allEqualTo(T a, T b, TArgs... args)
{
    return allEqualTo(a, b) && allEqualTo(a, args...);
}

if (allEqualTo(value, val_1, val_2, val_3)) {
    ....
}
模板
布尔·阿勒夸托(T a,T b)
{
返回a==b;
}
模板
布尔·阿勒夸托(T a、T b、TArgs…args)
{
返回allEqualTo(a,b)和&allEqualTo(a,args…);
}
if(allEqualTo(值,val_1,val_2,val_3)){
....
}

如果您使用范围库,您只需使用
全部

// Using Range-v3: https://ericniebler.github.io/range-v3/index.html
if (ranges::v3::all_of({val_1, val_2, val_3},
    [value](auto const& other) { return value == other; })) {
    // ...
}
您可以使用帮助器进一步简化它:

// Note: Prior to C++17, this could lead to ODR violations.
// After C++17, this will be an inline variable, thus this is fine.
// If using in C++14 or before, write std::equal_to<>{} instead of std::equal_to{}.
constexpr auto equal_to = boost::hof::partial(std::equal_to{});

// ...

if (ranges::v3::all_of({val1, val_2, val_3}, equal_to(value))) {
    // ...
}
//注意:在C++17之前,这可能会导致ODR冲突。
//在C++17之后,这将是一个内联变量,因此这很好。
//如果在C++14或更早版本中使用,请将std::equal_写入{},而不是将std::equal_写入{}。
constexpr auto equal_to=boost::hof::partial(std::equal_to{});
// ...
if(ranges::v3::all_of({val1,valu 2,valu 3},等于(value))){
// ...
}

各种比较运算符都受支持

交叉型双任意_,如:

any_of{1,2,3} == any_of{3.14, 5.7, 1.0}

将无法编译,因为两个
=
=
都可以
任何
工作。

否。听起来像是XY问题。这是什么用例?每个UDL表单都列在cppreference中:。此表单未列出。因此,它是不允许的。如果您确实想确定,可以检查标准itself@NathanOliver我正在努力“扩展”当前C++语法(这是一个有趣的小项目……)主要的想法是简化:<代码>((Valu1==value)&(Valu2==value)& &(Valu3== value))/>此:<代码>(STD:RealAlsiSeriSt{{Valay1,Valay2,Valy3}==value)< /C> >(OFC带有重载运算符:<代码>布尔运算符==(标准::初始值设定项\u列表常数和列表,T常数和参考)
)…我想编辑我需要在其中键入
std::initializer\u list
的部分,我发现我可以将其更改为自定义-literal@cukier9a7b5不要为你不拥有的类型重载运算符。你应该使用你自己的类型,而不是
std::initializer\u list
。除此之外,如果你使用范围库,你可以得到
if(所有({val_1,val_2,val_3},等于(值)))
用户定义的文本是带有用户定义后缀的文本。大括号列表不是一个开头的文本。不要重载该类型命名空间之外的类型的运算符,这会导致令人惊讶和恼火的行为。并且不要将运算符注入
命名空间std
,因为这会导致程序格式错误。简言之,不要“t重载
std
模板上的运算符。并修复您的示例,使其不成为代码气味。:@Yakk AdamNevraumont如果我要创建一个带有私有成员的“tag”类
std::array\u list
,则构造函数:
tag(std::array const&list):\u list(std::move(list)){/code>和一个预先指定的重载
bool运算符==(std::array const&list,T const&ref)
?这能解决“格式错误的程序”问题吗?最终结果如下:
如果(tag{4,4,4,4,4}==4){/*../../}
(2)对不起,我犯了一个错误,在使用tag类时,操作符应该是这样的:
friend bool操作符==(tag const&list,T const&ref)
与我上面发布的不一样。@cukier9a7b5我只是从
std::array
继承过来的。让开始/结束的东西都能正常工作。出于某种原因,我总是忘了提升有多有用。谢谢。这很恰当。
template<class T, std::size_t N>
struct any_of:std::array<T, N> {
  #define MAKE_OPERATOR( OPERATOR ) \
    template<class U, \
      std::enable_if_t< std::is_same<void, std::void_t< \
        decltype( std::declval<T const&>() == std::declval<U const&>() ) \
      >>{}, bool> =true \
    > \
    friend bool operator OPERATOR ( any_of const& lhs, U const& rhs) { \
      return std::any_of( \
        lhs.begin(), lhs.end(), \
        [&](auto&& lhs){ return lhs OPERATOR rhs; } \
      ); \
    } \
    template<class U, \
      std::enable_if_t< std::is_same<void, std::void_t< \
        decltype( std::declval<U const&>() == std::declval<T const&>() ) \
      >>{} && !std::is_same< U, any_of >{} , bool> =true \
    > \
    friend bool operator OPERATOR ( U const& lhs, any_of const& rhs) { \
      return std::any_of( \
        rhs.begin(), rhs.end(), \
        [&](auto&& rhs){ return lhs OPERATOR rhs; } \
      ); \
    }
  MAKE_OPERATOR(==)
  MAKE_OPERATOR(!=)
  MAKE_OPERATOR(<)
  MAKE_OPERATOR(<=)
  MAKE_OPERATOR(>=)
  MAKE_OPERATOR(>)
  #undef MAKE_OPERATOR
  explicit any_of( std::array<T, N> arr):std::array<T, N>(std::move(arr)) {}
  template<class...Ts>
  explicit any_of( T t, Ts... ts ):std::array<T, N>{ std::move(t), std::move(ts)... } {}
  any_of( any_of const& )=delete;
  any_of& operator=( any_of const& )=delete;
  any_of()=delete;
};
template<class T, std::size_t N>
any_of(T(&)[N]) -> any_of<T,N>;
template<class T, class...Ts>
any_of(T, Ts...) -> any_of<T, 1+sizeof...(Ts)>;
if (any_of{1,2,3} == 2) {
    std::cout << "2 is there\n";
}
if (! (any_of{1,2,3} == 7) ){
    std::cout << "7 is not there\n";
}

if (any_of{1,2,3} == any_of{5,6,1}) {
    std::cout << "overlap!\n";
}
if (!(any_of{1,2,3} == any_of{5,6,7})) {
    std::cout << "no overlap!\n";
}
2 is there
7 is not there
overlap!
no overlap!
any_of{1,2,3} == any_of{3.14, 5.7, 1.0}