Type Inference در ++C

Type Inference in C Plus Plus

16 اردیبهشت 1401
Type-Inference-in-C-Plus-Plus-2

استنباط نوع (Type Inference) به نتیجه‌گیری خودکار نوع داده از یک عبارت در زبان برنامه‌نویسی اشاره دارد. قبل از 11++C، هر نوع داده باید صریحا در زمان کامپایل اعلام شود و مقادیر یک عبارت در زمان اجرا (runtime) محدود بودند، اما بعد از نسخه‌های جدید ++C، کلمات کلیدی بسیاری اضافه شدند که به برنامه‌نویس امکان واگذاری نتیجه‌گیری نوع را به خود کامپایلر می‌داد.

با قابلیت Type Inference، می‌توانید زمان کمتری به نوشتن کار‌هایی که کامپایلر از قبل می‌داند، اختصاص دهید. همان‌طور که همه‌ی انواع تنها در مرحله‌ی کامپایلر نتیجه‌گیری می‌شوند، زمان کامپایل‌کردن کمی افزایش می‌یابد، اما تاثیری در زمان اجرای برنامه ندارد.

  1. کلمه‌‌‌ی کلیدی auto: کلمه‌ی کلیدی auto معین می‌کند که نوع متغیری که اعلام‌شده، به طور خودکار از مقداردهی اولیه‌اش نتیجه‌گیری خواهد شد. درمورد توابع، اگر نوع برگشتی‌اش auto باشد، توسط نوع برگشتی عبارت زمان اجرا ارزیابی می‌شود. استفاده‌ از auto برای اجتناب از مقداردهی‌اولیه طولانی، هنگام ایجاد پیمایشگر‌ها برای نگه‌دارنده‌ها خوب است.

نکته: متغیر اعلام‌شده با کلمه‌ی کلیدی auto باید در زمان اعلام شدنش مقدار‌دهی‌اولیه شود، در غیراینصورت یک خطای زمان کامپایل دریافت خواهد شد.

// C++ program to demonstrate working of auto
// and type inference
 
#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    // auto a; this line will give error
    // because 'a' is not initialized at
    // the time of declaration
    // a=33;
 
    // see here x ,y,ptr are
    // initialised at the time of
    // declaration hence there is
    // no error in them
    auto x = 4;
    auto y = 3.37;
    auto ptr = &x;
    cout << typeid(x).name() << endl
         << typeid(y).name() << endl
         << typeid(ptr).name() << endl;
 
    return 0;
}

خروجی قطعه‌کُد بالا به این صورت است:

i
d
Pi

نکته: از typeid برای دریافت نوع متغیر‌ها استفاده کردیم.

Typeid یک عملگر است که در جایی که نوع پویای یک شئ نیاز به شناختن داشته باشد، استفاده می‌شود. ()typeid(x).name نوع داده‌ی x را برمی‌گرداند. برای مثال این عملگر، i را برای اعداد برمی‌گرداند، d را برای اعشار، Pi را برای اشاره‌گر به نوع عددی و غیره. اما درواقع نام برگشت‌داده شده عمدتا وابسته به کامپایلر است.

استفاده‌ از auto برای اجتناب از مقداردهی‌اولیه طولانی هنگام ایجاد پیمایشگر‌ها برای نگه‌دارنده‌ها خوب است.

// C++ program to demonstrate that we can use auto to
// save time when creating iterators
 
#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    // Create a set of strings
    set<string> st;
    st.insert({ "geeks", "for", "geeks", "org" });
 
    // 'it' evaluates to iterator to set of string
    // type automatically
    for (auto it = st.begin(); it != st.end(); it++)
        cout << *it << " ";
 
    return 0;
}

خروجی قطعه‌کد بالا به این صورت است:

for geeks org

نکته: auto به نوع int تبدیل می‌شود، اگر حتی یک ارجاع عددی به آن اختصاص داده شود. برای ساختن نوع مرجع، از& auto استفاده می‌کنیم.

  • تابعی که یک نوع ارجاع به int برگشت می‌دهد: ;{}() int& fun
  • m پیش‌فرض نوع int خواهد بود به جای این‌که نوع &int باشد: auto m = fun();
  • n نوع &int است، چرا که از علامت & با کلمه‌ی کلیدی auto استفاده شده است: ;()auto& n = fun

2. کلمه‌ی کلیدی decltype: این کلمه‌ی کلیدی نوع اعلام شده یک عنصر یا نوع یک عبارت را بررسی می‌کند. کلمه‌ی کلیدی auto به شما اجازه‌ی اعلام یک متغیر با یک نوع خاص می‌دهد، درحالی‌که کلمه‌ی کلیدی decltype به شما اجازه‌ی استخراج نوع از متغیر می‌دهد، بنابراین کلمه‌ی کلیدی decltype به نوعی یک عملگر است که نوع را از عبارت ارسال‌شده ارزیابی می‌کند.

توضیح کلمه‌ی کلید بالا و استفاده‌ آنها در زیر آمده است:

// C++ program to demonstrate use of decltype
#include <bits/stdc++.h>
using namespace std;
 
int fun1() { return 10; }
char fun2() { return 'g'; }
 
int main()
{
    // Data type of x is same as return type of fun1()
    // and type of y is same as return type of fun2()
    decltype(fun1()) x;
    decltype(fun2()) y;
 
    cout << typeid(x).name() << endl;
    cout << typeid(y).name() << endl;
 
    return 0;
}

خروجی قطعه‌کد بالا به این صورت است:

i
c

مثال زیر نیز استفاده از کلمه‌ی کلیدی decltype را نشان می‌دهد:

// C++ program to demonstrate use of decltype
#include <bits/stdc++.h>
using namespace std;
 
// Driver Code
int main()
{
    int x = 5;
 
    // j will be of type int : data type of x
    decltype(x) j = x + 5;
 
    cout << typeid(j).name();
 
    return 0;
}

خروجی قطعه‌کد بالا به این صورت است:

i

برنامه‌ای که هم استفاده‌ی auto و هم استفاده‌ی decltype را نشان می‌دهد.

در قطعه‌کُد زیر تابع الگوی ()min_type است که کوچکترین عدد را بین 2 عدد برمی‌گرداند. نوع برگشتی با استفاده از نوع کوچکترین عدد بین دو عدد مشخص می‌شود.

// C++ program to demonstrate use of decltype in functions
#include <bits/stdc++.h>
using namespace std;
 
// A generic function which finds minimum of two values
// return type is type of variable which is minimum
template <class A, class B>
auto findMin(A a, B b) -> decltype(a < b ? a : b)
{
    return (a < b) ? a : b;
}
 
// driver function to test various inference
int main()
{
    // This call returns 3.44 of double type
    cout << findMin(4, 3.44) << endl;
 
    // This call returns 3 of double type
    cout << findMin(5.4, 3) << endl;
 
    return 0;
}

خروجی قطعه‌کُد بالا به این صورت است:

3.44
3

decltype درمقابل typeid

  • Decltype اطلاعات نوع را در زمان کامپایل فراهم می‌کند، درحالی‌که typeid در زمان اجرا این اطلاعات را فراهم می‌کند.
  • بنابراین، اگر یک ارجاع کلاس پایه (یا اشاره‌گر) به یک شئ کلاس مشتق‌شده اشاره کند، decltype نوع را به عنوان ارجاع (یا اشاره‌گر) کلاس پایه فراهم می‌کند، اما typeid نوع ارجاع یا اشاره‌گر مشتق‌شده را فراهم می‌کند.

منبع: وب سایت geeksforgeeks

نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.