ফাংশন পয়েন্টার হিসাবে ক্যাপচারিং ল্যাম্বদা পাস করা


210

ফাংশন পয়েন্টার হিসাবে ল্যাম্বডা ফাংশনটি পাস করা কি সম্ভব? যদি তা হয় তবে আমি অবশ্যই ভুলভাবে কিছু করছি কারণ আমি একটি সংকলন ত্রুটি পাচ্ছি।

নিম্নলিখিত উদাহরণ বিবেচনা করুন

using DecisionFn = bool(*)();

class Decide
{
public:
    Decide(DecisionFn dec) : _dec{dec} {}
private:
    DecisionFn _dec;
};

int main()
{
    int x = 5;
    Decide greaterThanThree{ [x](){ return x > 3; } };
    return 0;
}

আমি এটি সংকলনের চেষ্টা করার সময় আমি নিম্নলিখিত সংকলন ত্রুটি পেয়েছি:

In function 'int main()':
17:31: error: the value of 'x' is not usable in a constant expression
16:9:  note: 'int x' is not const
17:53: error: no matching function for call to 'Decide::Decide(<brace-enclosed initializer list>)'
17:53: note: candidates are:
9:5:   note: Decide::Decide(DecisionFn)
9:5:   note: no known conversion for argument 1 from 'main()::<lambda()>' to 'DecisionFn {aka bool (*)()}'
6:7:   note: constexpr Decide::Decide(const Decide&)
6:7:   note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const Decide&'
6:7:   note: constexpr Decide::Decide(Decide&&)
6:7:   note: no known conversion for argument 1 from 'main()::<lambda()>' to 'Decide&&'

হজম করার জন্য এটি একটি ত্রুটি বার্তার হেক, তবে আমি মনে করি যে আমি এর থেকে বেরিয়ে যাচ্ছি তা হ'ল ল্যাম্বডাটিকে একটি হিসাবে বিবেচনা করা constexprযায় না তাই আমি এটি ফাংশন পয়েন্টার হিসাবে পাস করতে পারি না? আমি xপাশাপাশি কনস্ট তৈরির চেষ্টা করেছি , তবে এটি কোনওরকম সাহায্য করবে বলে মনে হয় না।


34
ল্যাম্বদা কেবল কোনও কিছু ক্যাপচার না করলে পয়েন্টার ফাংশন করতে ক্ষয় হতে পারে।
জারোড 42


উত্তর:


205

একটি ল্যাম্বডা কেবলমাত্র ফাংশন পয়েন্টারে রূপান্তরিত হতে পারে যদি তা ক্যাপচার না করে, সি ++ 11 স্ট্যান্ডার্ড বিভাগের খসড়া 5.1.2 [expr.prim.lambda] বলেছেন ( জোর খনি ):

ল্যাম্বডা-ক্যাপচার ছাড়াই ল্যাম্বডা-এক্সপ্রেশনটির জন্য ক্লোজারের ধরণটিতে ক্লোজার টাইপের ফাংশন কল অপারেটরের মতো একই প্যারামিটার এবং রিটার্নের ধরণের বৈশিষ্ট্যযুক্ত একটি সার্বজনীন অ-ভার্চুয়াল নন-স্পষ্ট কনস্ট রূপান্তর ফাংশন রয়েছে । এই রূপান্তর ফাংশনটির মাধ্যমে ফিরে আসা মানটি কোনও ফাংশনের ঠিকানা হবে, যখন অনুরোধ করা হয়, ক্লোজার টাইপের ফাংশন কল অপারেটরকে অনুরোধ করার মতোই প্রভাব ফেলে।

দ্রষ্টব্য, সিপ্রেফারেন্স এছাড়াও লাম্বদা ফাংশনগুলিতে তাদের বিভাগে এটি কভার করে

সুতরাং নিম্নলিখিত বিকল্পগুলি কাজ করবে:

typedef bool(*DecisionFn)(int);

Decide greaterThanThree{ []( int x ){ return x > 3; } };

এবং তাই এটি হবে:

typedef bool(*DecisionFn)();

Decide greaterThanThree{ [](){ return true ; } };

এবং 5gon12eder হিসাবে উল্লেখ করা হয়েছে, আপনি এটি ব্যবহার করতে পারেন std::functionতবে লক্ষ্য করুন যে std::functionএটি ভারী ওজন , সুতরাং এটি কোনও ব্যয়-স্বল্প বাণিজ্য নয়।


2
পার্শ্ব দ্রষ্টব্য: সি স্টাফ দ্বারা ব্যবহৃত একটি সাধারণ সমাধান হ'ল void*একমাত্র পরামিতি হিসাবে পাস করা। এটিকে সাধারণত একটি "ব্যবহারকারী পয়েন্টার" বলা হয়। এটি তুলনামূলকভাবে কম ওজনের, তবে আপনার mallocকিছুটা জায়গা প্রয়োজন বলেও মনে করেন না।
ফান্ড মনিকার লসুইট

94

শফিক ইয়াঘমুরের উত্তর সঠিকভাবে ব্যাখ্যা করে যে ল্যাম্বডায় ক্যাপচার থাকলে ফাংশন পয়েন্টার হিসাবে কেন পাস করা যায় না। আমি সমস্যার জন্য দুটি সহজ সমাধান দেখাতে চাই।

  1. std::functionকাঁচা ফাংশন পয়েন্টারের পরিবর্তে ব্যবহার করুন ।

    এটি একটি খুব পরিষ্কার সমাধান। তবে নোট করুন যে এতে মুছে যাওয়া টাইপটির জন্য কিছু অতিরিক্ত ওভারহেড অন্তর্ভুক্ত রয়েছে (সম্ভবত ভার্চুয়াল ফাংশন কল)।

    #include <functional>
    #include <utility>
    
    struct Decide
    {
      using DecisionFn = std::function<bool()>;
      Decide(DecisionFn dec) : dec_ {std::move(dec)} {}
      DecisionFn dec_;
    };
    
    int
    main()
    {
      int x = 5;
      Decide greaterThanThree { [x](){ return x > 3; } };
    }
  2. একটি ল্যাম্বডা এক্সপ্রেশন ব্যবহার করুন যা কোনও কিছুই ক্যাপচার করে না।

    যেহেতু আপনার ভবিষ্যদ্বাণীটি কেবলমাত্র একটি বুলিয়ান ধ্রুবক, নিম্নলিখিতটি দ্রুত বর্তমান সমস্যাটি সম্পর্কে দ্রুত কাজ করবে। কেন এবং কীভাবে এটি কাজ করছে তার একটি ভাল ব্যাখ্যার জন্য এই উত্তরটি দেখুন ।

    // Your 'Decide' class as in your post.
    
    int
    main()
    {
      int x = 5;
      Decide greaterThanThree {
        (x > 3) ? [](){ return true; } : [](){ return false; }
      };
    }

4
@ টিটিসি কেন এটি কাজ করে তার বিশদ জানতে এই প্রশ্নটি দেখুন
শফিক ইয়াঘমোর ২

নোট করুন যে সাধারণভাবে, আপনি যদি সংকলনের সময় ক্যাপচার ডেটা জানেন, আপনি এটিকে ডেটা টাইপ করে রূপান্তর করতে পারেন এবং তারপরে কোনও ক্যাপচার না রেখে ল্যাম্বদা পেয়ে ফিরে আসছেন - এই উত্তরটি দেখুন যা আমি সবেমাত্র অন্য একটি প্রশ্নে লিখেছি (@ ধন্যবাদ 5gon12eder এর উত্তর এখানে)।
ড্যান-ম্যান

পয়েন্টার ফাংশনের চেয়ে অবজেক্টটির দীর্ঘতর আয়ু হওয়া উচিত নয়? আমি এটির জন্য ব্যবহার করতে চাই glutReshapeFunc
ar2015

আমি এই পরামর্শটি সুপারিশ করি না, যে জিনিসগুলি যাদুবিদ্যার সাথে কাজ করে, নতুন ত্রুটিগুলি প্রবর্তন করে। এবং সেই ত্রুটিগুলির সাথে অনুশীলনগুলি। আপনি যদি std :: ফাংশনটি ব্যবহার করতে চান তবে আপনার স্ট্যান্ড :: ফাংশনটি ব্যবহার করতে পারে এমন সমস্ত ধরণের উপায় দেখতে হবে। কারণ কিছু উপায়ে এমন কিছু হতে পারে যা আপনি চান না।
TheNegative

1
এটি প্রশ্নের উত্তর দেয় না। কেউ যদি std::functionএকটি ল্যাম্বডা ব্যবহার করতে পারে - তবে তারা কেন করবে না? খুব কমপক্ষে এটি আরও পাঠযোগ্য পাঠ্য সিনট্যাক্স। সাধারণত সি লাইব্রেরির সাথে ইন্টারঅ্যাক্ট করার জন্য একটি ফাংশন পয়েন্টার ব্যবহার করা প্রয়োজন (প্রকৃতপক্ষে, কোনও বাহ্যিক লাইব্রেরির সাথে) , এবং নিশ্চিত যে আপনি কোনও স্টাড :: ফাংশন বা ল্যাম্বদা গ্রহণ করতে এটি পরিবর্তন করতে পারবেন না।
হাই-এঞ্জেল

40

ল্যাম্বডা এক্সপ্রেশন এমনকি ক্যাপচার হওয়াগুলিও একটি ফাংশন পয়েন্টার (সদস্য ফাংশনটির পয়েন্টার) হিসাবে পরিচালনা করা যায়।

এটি মুশকিল কারণ একটি ল্যাম্বডা এক্সপ্রেশন কোনও সাধারণ ফাংশন নয়। এটি আসলে অপারেটর () সহ একটি বস্তু।

আপনি যখন সৃজনশীল হন, আপনি এটি ব্যবহার করতে পারেন! স্ট্যান্ড :: ফাংশনের স্টাইলে একটি "ফাংশন" শ্রেণীর কথা ভাবেন। আপনি যদি বস্তুটি সংরক্ষণ করেন তবে আপনি ফাংশন পয়েন্টারটিও ব্যবহার করতে পারেন।

ফাংশন পয়েন্টার ব্যবহার করতে, আপনি নিম্নলিখিতটি ব্যবহার করতে পারেন:

int first = 5;
auto lambda = [=](int x, int z) {
    return x + z + first;
};
int(decltype(lambda)::*ptr)(int, int)const = &decltype(lambda)::operator();
std::cout << "test = " << (lambda.*ptr)(2, 3) << std::endl;

"Std :: ফাংশন" এর মতো কাজ করা শুরু করতে পারে এমন একটি শ্রেণি তৈরি করতে প্রথমে আপনার অবজেক্ট এবং ফাংশন পয়েন্টার সঞ্চয় করার চেয়ে ক্লাস / কাঠামো প্রয়োজন। এছাড়াও এটি কার্যকর করতে আপনার অপারেটর প্রয়োজন:

// OT => Object Type
// RT => Return Type
// A ... => Arguments
template<typename OT, typename RT, typename ... A>
struct lambda_expression {
    OT _object;
    RT(OT::*_function)(A...)const;

    lambda_expression(const OT & object)
        : _object(object), _function(&decltype(_object)::operator()) {}

    RT operator() (A ... args) const {
        return (_object.*_function)(args...);
    }
};

এটির সাহায্যে আপনি এখন যেমন ক্যাপচারড, নন-ক্যাপচারড ল্যাম্বডাস চালাতে পারেন আপনি যেমন আসলটি ব্যবহার করছেন:

auto capture_lambda() {
    int first = 5;
    auto lambda = [=](int x, int z) {
        return x + z + first;
    };
    return lambda_expression<decltype(lambda), int, int, int>(lambda);
}

auto noncapture_lambda() {
    auto lambda = [](int x, int z) {
        return x + z;
    };
    return lambda_expression<decltype(lambda), int, int, int>(lambda);
}

void refcapture_lambda() {
    int test;
    auto lambda = [&](int x, int z) {
        test = x + z;
    };
    lambda_expression<decltype(lambda), void, int, int>f(lambda);
    f(2, 3);

    std::cout << "test value = " << test << std::endl;
}

int main(int argc, char **argv) {
    auto f_capture = capture_lambda();
    auto f_noncapture = noncapture_lambda();

    std::cout << "main test = " << f_capture(2, 3) << std::endl;
    std::cout << "main test = " << f_noncapture(2, 3) << std::endl;

    refcapture_lambda();

    system("PAUSE");
    return 0;
}

এই কোডটি ভিএস ২০১৫ এর সাথে কাজ করে

04.07.17 আপডেট করুন:

template <typename CT, typename ... A> struct function
: public function<decltype(&CT::operator())(A...)> {};

template <typename C> struct function<C> {
private:
    C mObject;

public:
    function(const C & obj)
        : mObject(obj) {}

    template<typename... Args> typename 
    std::result_of<C(Args...)>::type operator()(Args... a) {
        return this->mObject.operator()(a...);
    }

    template<typename... Args> typename 
    std::result_of<const C(Args...)>::type operator()(Args... a) const {
        return this->mObject.operator()(a...);
    }
};

namespace make {
    template<typename C> auto function(const C & obj) {
        return ::function<C>(obj);
    }
}

int main(int argc, char ** argv) {
   auto func = make::function([](int y, int x) { return x*y; });
   std::cout << func(2, 4) << std::endl;
   system("PAUSE");
   return 0;
}

বাহ এটা আশ্চর্যজনক! সুতরাং আমরা কেবল ল্যাম্পডা ক্লাসের অভ্যন্তরীণ পয়েন্টারগুলি (সদস্য ফাংশন অপারেটর ()) এর সাহায্যে একটি মোড়ক ক্লাসে সঞ্চিত ল্যাম্বডাস প্রার্থনা করতে পারি !! ক্যাচাল !! আমাদের তখন কেন std :: ফাংশন দরকার? এবং স্বয়ংক্রিয়ভাবে / পাস করা ল্যাম্বদা থেকেই এই "ইনট" পরামিতিগুলি স্বয়ংক্রিয়ভাবে কাটাতে ল্যাম্বডএ এক্সপ্রেশন <ডিক্লাইপ (ল্যাম্বডা), ইনট, ইনট, ইনট> করা সম্ভব?
বার্নে

2
আমি আমার নিজস্ব কোডের একটি সংক্ষিপ্ত সংস্করণ যুক্ত করেছি। এটি একটি সাধারণ অটোর সাথে কাজ করা উচিত f = make :: ফাংশন (ল্যাম্বদা); তবে আমি বেশ শিউর আছি আপনি প্রচুর পরিস্থিতি পাবেন আমার কোডটি কাজ করবে না। স্ট্যান্ড :: ফাংশনটি এর চেয়ে আরও ভালভাবে নির্মিত এবং আপনি যখন কাজ করছেন তখন যাওয়া উচিত। এটি এখানে শিক্ষা এবং ব্যক্তিগত ব্যবহারের জন্য।
Noxxer

14
এই সমাধানটি operator()প্রয়োগের মাধ্যমে ল্যাম্বডাকে কল করার সাথে জড়িত , তাই যদি আমি এটি সঠিকভাবে পড়ছি তবে আমি মনে করি না যে এটি সি-স্টাইলের ফাংশন পয়েন্টার ব্যবহার করে ল্যাম্বডাকে কল করতে কাজ করবে, তাইনা ? এটিই মূল প্রশ্নটি চেয়েছিল।
রেমি লিবিউ

13
আপনি দাবি করেছেন যে ল্যাম্বডাস ফাংশন পয়েন্টার হিসাবে পরিচালনা করা যেতে পারে, যা আপনি করেননি। ল্যাম্বডা ধরে রাখতে আপনি অন্য একটি জিনিস তৈরি করেছেন, যা কিছুই করে না, আপনি কেবল আসল ল্যাম্বডাকে ব্যবহার করতে পারতেন।
পাসার

9
এটি "ফাংশন পয়েন্টার হিসাবে ল্যাম্বডাকে ক্যাপচার করছে না"। এটি "অন্যান্য জিনিসের মধ্যে ফাংশন পয়েন্টার ধারণ করে এমন একটি বস্তু হিসাবে ল্যাম্বদা ক্যাপচার করছে"। পার্থক্য একটি বিশ্ব আছে।
এন। 'সর্বনাম' মি।

15

লম্বডাস ক্যাপচারিংকে ফাংশন পয়েন্টারে রূপান্তর করা যায় না, যেমন এই উত্তরটি উল্লেখ করেছে।

তবে এটি প্রায়শই কোনও এপিআইতে ফাংশন পয়েন্টার সরবরাহ করতে বেশ ব্যথা হয়। এটি করার জন্য প্রায়শই উল্লেখ করা পদ্ধতি হ'ল কোনও ফাংশন সরবরাহ করা এবং এটির সাথে একটি স্ট্যাটিক অবজেক্ট কল করা।

static Callable callable;
static bool wrapper()
{
    return callable();
}

এটা ক্লান্তিকর। আমরা এই ধারণাটি আরও গ্রহণ করি wrapperএবং জীবনকে আরও সহজ করার এবং তৈরি করার প্রক্রিয়াটি স্বয়ংক্রিয় করে তুলি।

#include<type_traits>
#include<utility>

template<typename Callable>
union storage
{
    storage() {}
    std::decay_t<Callable> callable;
};

template<int, typename Callable, typename Ret, typename... Args>
auto fnptr_(Callable&& c, Ret (*)(Args...))
{
    static bool used = false;
    static storage<Callable> s;
    using type = decltype(s.callable);

    if(used)
        s.callable.~type();
    new (&s.callable) type(std::forward<Callable>(c));
    used = true;

    return [](Args... args) -> Ret {
        return Ret(s.callable(std::forward<Args>(args)...));
    };
}

template<typename Fn, int N = 0, typename Callable>
Fn* fnptr(Callable&& c)
{
    return fnptr_<N>(std::forward<Callable>(c), (Fn*)nullptr);
}

এবং হিসাবে এটি ব্যবহার করুন

void foo(void (*fn)())
{
    fn();   
}

int main()
{
    int i = 42;
    auto fn = fnptr<void()>([i]{std::cout << i;});
    foo(fn);  // compiles!
}

লাইভ দেখান

এটি প্রতিটি ইভেন্টে মূলত একটি বেনামী ফাংশন ঘোষণা করছে fnptr

নোট করুন যে অনুরূপ fnptrপূর্বে লিখিত callableপ্রদত্ত কলগুলি একই ধরণের ওভাররাইটের অনুরোধ । আমরা intপ্যারামিটার সহ একটি নির্দিষ্ট ডিগ্রীতে এটি প্রতিকার করি N

std::function<void()> func1, func2;
auto fn1 = fnptr<void(), 1>(func1);
auto fn2 = fnptr<void(), 2>(func2);  // different function

এন পূর্ণসংখ্যা ঘোষণার জন্য বাধ্য করা হ'ল সংকলনের সময় ফাংশন পয়েন্টারগুলিকে ওভাররাইট করা এড়াতে ক্লায়েন্টকে মনে রাখার মার্জিত উপায়।
fiorentinoing

2

সি ফাংশন পয়েন্টার হিসাবে ল্যাম্বডা ব্যবহারের জন্য একটি শর্টকাট হ'ল:

"auto fun = +[](){}"

কার্লকে এক্সম্যাম্পল হিসাবে ব্যবহার করে ( কার্ল ডিবাগ তথ্য )

auto callback = +[](CURL* handle, curl_infotype type, char* data, size_t size, void*){ //add code here :-) };
curl_easy_setopt(curlHande, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curlHande,CURLOPT_DEBUGFUNCTION,callback);

3
সেই ল্যাম্বদার কোনও ক্যাপচার নেই। ওপি'র ইস্যুটি হ'ল ক্যাপচার, ফাংশন পয়েন্টার টাইপটি কাটাতে হবে না (যা +কৌশলটি আপনাকে পেয়ে থাকে)।
স্নেফটেল

2

যদিও বিভিন্ন কারণে টেমপ্লেট পদ্ধতির চালাক, তবুও ল্যাম্বডোর জীবনচক্রটি এবং ধরা পড়া ভেরিয়েবলগুলি মনে রাখা গুরুত্বপূর্ণ। যদি কোনও ল্যাম্বডা পয়েন্টারের কোনও রূপ ব্যবহার করা হয় এবং ল্যাম্বদা নিম্নমুখী ধারাবাহিকতা না হয় তবে কেবল একটি অনুলিপি [=] ল্যাম্বডা ব্যবহার করা উচিত। অর্থাৎ, তারপরেও, স্ট্যাকের একটি ভেরিয়েবলের জন্য একটি পয়েন্টার ক্যাপচার করা যদি সেই বন্দী পয়েন্টার (স্ট্যাক আনওয়াইন্ড) এর জীবনকাল ল্যাম্বডারের জীবনকাল থেকে সংক্ষিপ্ত হয় তবে আনস্যাফ করা হয়।

পয়েন্টার হিসাবে ল্যাম্বডা ক্যাপচার জন্য একটি সহজ সমাধান হ'ল:

auto pLamdba = new std::function<...fn-sig...>([=](...fn-sig...){...});

যেমন, new std::function<void()>([=]() -> void {...}

কেবল পরে মনে রাখবেন delete pLamdbaযাতে লাম্বদা স্মৃতি ফাঁস হয় না তা নিশ্চিত হয়ে নিন। এখানে উপলব্ধি করার বিষয়টি গোপনীয় যে std::functionল্যাম্বডাস ল্যাম্বডাসকে ক্যাপচার করতে পারে (নিজেকে জিজ্ঞাসা করে যে এটি কীভাবে কাজ করে) এবং এছাড়াও যে উদারভাবে কাজ করার জন্য ল্যাম্বডা বাস্তবায়নে ল্যাম্বডা আকারের অ্যাক্সেস সরবরাহ করার জন্য পর্যাপ্ত অভ্যন্তরীণ তথ্য থাকা প্রয়োজন (এবং ধরা পড়েছে) ডেটা ( যে কারণে delete[ক্যাপচারিত ধরণের ডেস্ট্রাক্টরদের চালানো] কাজ করা উচিত।


কেন new- স্টাড :: ফাংশনটি নিয়ে বিরক্ত হ'ল ল্যাম্বদাটি ইতিমধ্যে স্তূপে সংরক্ষণ করে এবং কলটি মোছার কথা মনে রাখার প্রয়োজন এড়ায়।
ক্রিস ডড

0

সরাসরি উত্তর নয়, ল্যাম্বদা জাতীয় ধরণের বৈশিষ্ট্যগুলি গোপন করতে "কোডার" টেম্পলেট প্যাটার্নটি ব্যবহার করার জন্য সামান্য প্রকরণ এবং কোডটি সুন্দর এবং সরল রাখে।

আপনি কীভাবে সিদ্ধান্ত শ্রেণিটি ব্যবহার করতে চেয়েছিলেন তা আমি নিশ্চিত ছিলাম না সুতরাং আমাকে ক্লাসটি একটি ফাংশন ব্যবহার করে প্রসারিত করতে হবে। এখানে সম্পূর্ণ উদাহরণ দেখুন: https://godbolt.org/z/jtByqE

আপনার শ্রেণীর প্রাথমিক ফর্মটি দেখতে এইরকম হতে পারে:

template <typename Functor>
class Decide
{
public:
    Decide(Functor dec) : _dec{dec} {}
private:
    Functor _dec;
};

শ্রেণীর ধরণের অংশ হিসাবে আপনি এখানে ফাংশনটির ধরণটি যেমন ব্যবহার করেন:

auto decide_fc = [](int x){ return x > 3; };
Decide<decltype(decide_fc)> greaterThanThree{decide_fc};

আবার, আমি নিশ্চিত ছিলাম না যে আপনি কেন xএটি ক্যাপচার করছেন তা ল্যাম্বডায় যে প্যারামিটারটি রেখেছেন তা আরও বুদ্ধিমান করে (আমার কাছে) যাতে আপনি ব্যবহার করতে পারেন:

int result = _dec(5); // or whatever value

সম্পূর্ণ উদাহরণের জন্য লিঙ্কটি দেখুন


-2

অন্যদের দ্বারা যেমনটি উল্লেখ করা হয়েছিল আপনি ফাংশন পয়েন্টারের পরিবর্তে লাম্বডা ফাংশনটি প্রতিস্থাপন করতে পারেন। আমি এই পদ্ধতিটি আমার C ++ ইন্টারফেসে F77 ODE সলভার আরকেএসইউটিতে ব্যবহার করছি।

//C interface to Fortran subroutine UT
extern "C"  void UT(void(*)(double*,double*,double*),double*,double*,double*,
double*,double*,double*,int*);

// C++ wrapper which calls extern "C" void UT routine
static  void   rk_ut(void(*)(double*,double*,double*),double*,double*,double*,
double*,double*,double*,int*);

//  Call of rk_ut with lambda passed instead of function pointer to derivative
//  routine
mathlib::RungeKuttaSolver::rk_ut([](double* T,double* Y,double* YP)->void{YP[0]=Y[1]; YP[1]= -Y[0];}, TWANT,T,Y,YP,YMAX,WORK,UFLAG);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.