一个C ++“in”运算符没有残缺?

时间:2015-06-06 13:15:15

标签: c++ c++11

我想在C ++(11)中模拟Python的in运算符,在Python中使用immedate值。如:

if x in (1, 2, 3): ...

在C ++ 11中,似乎我已经接近能够做到这一点:

if (IsIn(x, { 1, 2, 3 }))
    {
    }


template<typename Val, Container cont>
bool IsIn(Val const &val, Container const &cont)
    {
    return boost::find(cont, val) != cont.end();
    }

但是(在g ++ - 4.8中)我得到了:

  

错误:没有匹配函数来调用'IsIn(MyType&amp;,&lt;大括号括号的初始化列表&gt;)'

我知道我可以做到这一点,但这有很多瑕疵:

if (IsIn(x, std::initializer_list<MyType>{1, 2, 3 })) ...

优雅的解决方案是什么?

更新:我对编译时与运行时的想法不够,我仍然无法确定是否有明显的赢家。我的IsIn(x, {})肯定有更多的运行时循环开销并复制initializer_list值,但也适用于任何容器。 ... == any_of(...机制肯定会编译为更严格的代码并且不会复制,但只适用于immediates(这是我的原始示例)而不是容器,而sytax(对我来说)似乎不太直接。

因为它是一种平局,所以我将其奖励给贡献者。

感谢大家的讨论!

4 个答案:

答案 0 :(得分:3)

解决方案就在我的鼻子底下......

template<typename Val>
bool IsIn(Val val, std::initializer_list<Val> const &cont)
    {
    return boost::find(cont, val) != cont.end(); // include <boost/range/algorithm.hpp>
    // Or if you don't want boost, include <algorithm>
    // return std::find(cont.begin(), cont.end(), val) != cont.end();
    }

答案 1 :(得分:2)

另一个小想法:

template<typename T, typename ... Args>
struct in_impl
{
    in_impl(T const& t, Args const& ... args) : val({t, args ...}) {}

    std::array<T, sizeof ...(Args) + 1> val;
};


template<typename T, typename ... Args>
bool operator==(T const& t, in_impl<T, Args ...> const& in)
{
    return std::find(std::begin(in.val), std::end(in.val), t) != std::end(in.val);
}


template<typename T, typename ... Args>
auto in(T const& t, Args const& ... args)
{
    return in_impl<T, Args ...>(t, args ...);
}

这可以用作

int main()
{
    if(1 == in(1,2,3) )
    {
        std::cout<<"1 is in"<<std::endl;
    }
}

DEMO

在获得领先类型T时可以更加小心,但这个想法应该变得清晰。

答案 2 :(得分:1)

我为无耻的插件道歉,但我认为它解决了OP的问题。

您可以使用this library

#include "smart_conditions.hpp"
using namespace smart_conditions;

// ...

if (x == any_of (1, 2, 3))
{
    // ...
}

它支持其他关系运算符,如果所有操作数在编译时都已知,在编译时工作constexpr),它使无副本 。另外,适用于混合类型,这意味着if (std::string("x") == any_of ("x", "y"))编译得很好。

答案 3 :(得分:0)

有两种情况,一种情况可以拨打std::find(container.begin(), container.end(), value),另一种情况可以拨打template<typename IteratorType, typename Type> bool contains ( IteratorType first, IteratorType last, Type const& value ) { return std::find ( first, last, value ) != last; } template <template <typename, typename ...> class ContainerType, typename KeyType, typename... Types> bool contains_key ( ContainerType <KeyType, Types ...> const& container , KeyType const& key ) { return container.find ( key ) != container.end ( ); }

User.objects.filter(username=username).update(is_staff=True)