কাস্টম স্টাড :: সেট তুলনামূলক ব্যবহার করে


105

আমি সংখ্যার পরিবর্তে ডিক্টরিজিক হওয়ার জন্য পূর্ণসংখ্যার সেটগুলিতে আইটেমগুলির ডিফল্ট ক্রমটি পরিবর্তন করার চেষ্টা করছি, এবং আমি g ++ দিয়ে সংকলন করতে নিম্নলিখিতটি পেতে পারি না:

file.cpp:

bool lex_compare(const int64_t &a, const int64_t &b) 
{
    stringstream s1,s2;
    s1 << a;
    s2 << b;
    return s1.str() < s2.str();
}

void foo()
{
    set<int64_t, lex_compare> s;
    s.insert(1);
    ...
}

আমি নিম্নলিখিত ত্রুটি পেয়েছি:

error: type/value mismatch at argument 2 in template parameter list for template<class _Key, class _Compare, class _Alloc> class std::set
error:   expected a type, got lex_compare

আমি কি ভুল করছি?

উত্তর:


158

আপনি একটি ফাংশন ব্যবহার করছেন যেখানে আপনার কোনও ফান্টর ব্যবহার করা উচিত (এমন একটি শ্রেণি যা () অপারেটরকে ওভারলোড করে যাতে এটি কোনও ফাংশনের মতো বলা যেতে পারে)।

struct lex_compare {
    bool operator() (const int64_t& lhs, const int64_t& rhs) const {
        stringstream s1, s2;
        s1 << lhs;
        s2 << rhs;
        return s1.str() < s2.str();
    }
};

আপনি ক্লাসের নামটি টাইপ প্যারামিটার হিসাবে ব্যবহার করেন

set<int64_t, lex_compare> s;

আপনি যদি ফান্টারের বয়লারপ্লেট কোডটি এড়াতে চান তবে আপনি একটি ফাংশন পয়েন্টারও ব্যবহার করতে পারেন (ধরে lex_compareনেওয়া একটি ফাংশন)।

set<int64_t, bool(*)(const int64_t& lhs, const int64_t& rhs)> s(&lex_compare);

4
@ ওমি: আপনি কোন সংকলকটি

1
@ ওমরি আপনি কোন সংকলক ব্যবহার করছেন?

4
@ ওমরি সি ++ স্ট্যান্ডার্ড বলছে যে দ্বিতীয় টেম্পলেট প্যারামিটারটি কোনও প্রকারের নাম হতে হবে - একটি ফাংশনের নাম কোনও প্রকারের নাম নয়।

6
ফাংশনের ধরণটি বোঝাতে আমরা ডিক্লাইপ (লেক্স_কম্পার) ব্যবহার করতে পারি?
লুইস চ্যান

2
@ লুইসচান সঠিক শব্দটি হবেstd::set<int64_t, decltype(&lex_compare)> s(&lex_compare)
নিশান্ত সিং

109

1. আধুনিক সি ++ 20 সমাধান

auto cmp = [](int a, int b) { return ... };
std::set<int, decltype(cmp)> s;

আমরা তুলক হিসাবে ল্যাম্বদা ফাংশন ব্যবহার করি । যথারীতি, তুলনাকারী বুলিয়ান মানটি ফিরিয়ে আনতে হবে, এটি সূচিত করে যে প্রথম যুক্তি হিসাবে যে উপাদানটি পাস হয়েছে তা নির্দিষ্ট কঠোর দুর্বল ক্রমটি সংজ্ঞায়িত করার পরে দ্বিতীয়টির আগে যাওয়ার কথা বিবেচনা করা হয় ।

অনলাইন ডেমো

2. আধুনিক সি ++ 11 সমাধান

auto cmp = [](int a, int b) { return ... };
std::set<int, decltype(cmp)> s(cmp);

সি ++ 20 এর আগে কনস্ট্রাক্টর সেট করার জন্য আমাদের ল্যাম্বদা পাস করতে হবে

অনলাইন ডেমো

৩. প্রথম সমাধানের মতো, তবে ল্যাম্বদার পরিবর্তে ফাংশন সহ

বুলিয়ান ফাংশন হিসাবে তুলনামূলক করুন

bool cmp(int a, int b) {
    return ...;
}

তারপরে এটি ব্যবহার করুন, হয় এইভাবে:

std::set<int, decltype(cmp)*> s(cmp);

অনলাইন ডেমো

বা এইভাবে:

std::set<int, decltype(&cmp)> s(&cmp);

অনলাইন ডেমো

৪. ()অপারেটরের সাথে কাঠামো ব্যবহার করে ওল্ড সমাধান solution

struct cmp {
    bool operator() (int a, int b) const {
        return ...
    }
};

// ...
// later
std::set<int, cmp> s;

অনলাইন ডেমো

৫. বিকল্প সমাধান: বুলিয়ান ফাংশন থেকে কাঠামো তৈরি করুন

বুলিয়ান ফাংশন নিন

bool cmp(int a, int b) {
    return ...;
}

এবং এটি ব্যবহার করে কাঠামো তৈরি করুন std::integral_constant

#include <type_traits>
using Cmp = std::integral_constant<decltype(&cmp), &cmp>;

অবশেষে, স্ট্রাক্টকে তুলনাকারী হিসাবে ব্যবহার করুন

std::set<X, Cmp> set;

অনলাইন ডেমো


3
উদাহরণস্বরূপ 1, সিএমপি কি কনস্ট্রাক্টরে পাস করা দরকার? ল্যাম্বডা টাইপটি কোনও টেম্পলেট ধরণের হিসাবে দেওয়া হিসাবে সেটটি নিজেই তৈরি করবে?
পিটুক

2
সি +++ এর তুলনায় @PeteUK কে কনস্ট্রাক্টরে পাস করতে হবে। সি ++ তে 20 টি কনস্ট্রাক্টর ছাড়াই আর্গুমেন্ট ব্যবহার করা যেতে পারে। প্রশ্নের জন্য আপনাকে ধন্যবাদ; উত্তর আপডেট হয়েছে
ডায়রালিক

1
@diralik প্রতিক্রিয়া এবং আপনার ইতিমধ্যে দুর্দান্ত উত্তরে আপডেট করার জন্য আপনাকে অনেক ধন্যবাদ।
পিটুক

1
জেনেরিক
ল্যাম্বদা

2
যে 5. পাগল। কেউ প্রতিদিন ভাষার নতুন কুলু এবং ক্র্যানি খুঁজে পান।
জানু হোয়েক

18

ইয়াকবির উত্তর আমাকে ফান্টারের বয়লারপ্লেটটি encapsulate করার জন্য একটি অ্যাডাপ্টার লিখতে অনুপ্রাণিত করে।

template< class T, bool (*comp)( T const &, T const & ) >
class set_funcomp {
    struct ftor {
        bool operator()( T const &l, T const &r )
            { return comp( l, r ); }
    };
public:
    typedef std::set< T, ftor > t;
};

// usage

bool my_comparison( foo const &l, foo const &r );
set_funcomp< foo, my_comparison >::t boo; // just the way you want it!

বাহ, আমি মনে করি যে এটি মূল্য ছিল!


17
মতামত একটি বিষয়, আমি অনুমান।

6

আপনি কোনও ফাংশন তুলকটিকে এটি মোড়ানো না করে ব্যবহার করতে পারেন:

bool comparator(const MyType &lhs, const MyType &rhs)
{
    return [...];
}

std::set<MyType, bool(*)(const MyType&, const MyType&)> mySet(&comparator);

যা আপনার টাইপের একটি সেট প্রয়োজন প্রতিবার টাইপ করতে জ্বালাতন করছে এবং যদি আপনি একই তুলক দিয়ে সমস্ত সেট তৈরি না করেন তবে সমস্যা সৃষ্টি করতে পারে।


3

std::less<> সাথে কাস্টম ক্লাস ব্যবহার করার সময় operator<

আপনি যদি নিজের কাস্টম শ্রেণীর সংকলন operator<সংজ্ঞায়িত করে এমন একটি সেট নিয়ে কাজ করছেন , তবে আপনি কেবল ব্যবহার করতে পারেনstd::less<>

Http://en.cppreferences.com/w/cpp/container/set/find এ উল্লিখিত হিসাবে C ++ 14 দুটি নতুন findএপিআই যুক্ত করেছে :

template< class K > iterator find( const K& x );
template< class K > const_iterator find( const K& x ) const;

যা আপনাকে করতে দেয়:

main.cpp

#include <cassert>
#include <set>

class Point {
    public:
        // Note that there is _no_ conversion constructor,
        // everything is done at the template level without
        // intermediate object creation.
        //Point(int x) : x(x) {}
        Point(int x, int y) : x(x), y(y) {}
        int x;
        int y;
};
bool operator<(const Point& c, int x) { return c.x < x; }
bool operator<(int x, const Point& c) { return x < c.x; }
bool operator<(const Point& c, const Point& d) {
    return c.x < d;
}

int main() {
    std::set<Point, std::less<>> s;
    s.insert(Point(1, -1));
    s.insert(Point(2, -2));
    s.insert(Point(0,  0));
    s.insert(Point(3, -3));
    assert(s.find(0)->y ==  0);
    assert(s.find(1)->y == -1);
    assert(s.find(2)->y == -2);
    assert(s.find(3)->y == -3);
    // Ignore 1234, find 1.
    assert(s.find(Point(1, 1234))->y == -1);
}

সংকলন এবং চালান:

g++ -std=c++14 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out

সম্পর্কিত আরও তথ্য এখানে std::less<>পাওয়া যাবে: স্বচ্ছ তুলকগুলি কী কী?

উবুন্টু 16.10, g++6.2.0 এ পরীক্ষিত ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.