簡體   English   中英

如何在C ++中為內置類型(例如整數)添加成員函數

[英]How to add member function for built-in types such as integer in C++

我正在使用C ++實現某些東西,我有一個類型索引簇,它包括兩個成員:一個是整數,另一個是結構,如下所示:

typedef int IndexA_t;
struct IndexB_t { ... };

這是一個要求,我想為這兩種類型添加一個通用函數(假設將其命名為fun1()),因為我想將它們傳遞給調用fun1()的模板函數,對於IndexB_t來說很容易實現但這讓我感到困惑,因為IndexA_t ,如何為整數(內置)類型引入函數成員? 我必須實現一個模擬int類型的類嗎? 它確實需要大量不必要的工作(許多操作員...),還有其他方法嗎?

非常感謝您的幫助,謝謝。

實現一個行為像int但可以擴展的類型不是太難。

#include <iostream>

class Int
{
  int m_i;
public:
  Int(int i) : m_i(i) {};
  operator int&() { return m_i; }
  operator int() const { return m_i; }
};

void func(int) {}

int main()
{
  // copy-assignment from int
  Int i = 2;
  i = 4+15;

  // Binding reference
  int& x = i;
  x = 2;

  // Implicit conversion in expression
  std::cout << i + 2 << '\n';

  // Implicit conversion in parameter
  func(i);
}

您可以按照玉米秸稈的建議進行操作,並使用與std::beginstd::end相同的技術。 它為定義begin / end成員函數的對象提供重載,並為使用該函數有意義的其他類型(在這種情況下為數組)提供重載。

在下面的示例中,我們有一個getval free函數,該函數為定義getval成員函數的類型提供重載,使用尾隨返回類型激活SFINAE。 然后,對於其他類型,它使用類型特征來確保僅允許使用整數類型,而拒絕所有其他類型,再次通過enable_if使用SFINAE。

這個示例是人為設計的 ,僅用於說明該技術,您可以采用該技術來實現所需的任何功能(問題並未詳細說明,所以我必須使用許可證)。 在以下情況下,通過將一個int轉換運算符添加到IndexB_t類顯然會更容易達到相同的效果,但這不是重點。

#include <iostream>
#include <type_traits>
using namespace std;

/* is_integer type trait */
template<typename T>
using is_integer = is_same<remove_cv_t<T>, int>;

template<typename T>
constexpr bool is_integer_v = is_integer<T>::value;

/* getval function definition */
template<typename T, 
         typename = enable_if_t<is_integer_v<T>>
        >
T getval(T i)
{ return i; }

template<typename T>
auto getval(T& t) -> decltype(t.getval())
{ return t.getval(); }

/* defined types */
typedef int IndexA_t;

class IndexB_t 
{ 
    int x;

    public:
    IndexB_t(int i) : x(i) {}

    int getval() const { return x; }
};

// a test struct with no `getval` member function.
struct NoGetVal {};

// driver function
int main()
{
    int i = 9;
    IndexB_t j = 10;
    IndexA_t k = 11;
    const int l = 12;
    volatile int m = 13;
    const volatile int n = 14;
    float a = 1.1;
    NoGetVal ngv;

    cout << getval(i) << '\n';
    cout << getval(j) << '\n';
    cout << getval(k) << '\n';
    cout << getval(l) << '\n';
    cout << getval(m) << '\n';
    cout << getval(n) << '\n';

    // disallowed as not int
    //cout << getval(a) << '\n';

    // disallowed no `getval` member function
    //cout << getval(ngv) << '\n';
}

因此,現在對於整數基元和充當整數的對象有了一個一致的接口。

您可能希望使用std::is_integral減輕對原始類型重載中允許的類型的限制。 由你決定。

這是c ++ 14,但可以通過使用enable_if而不是enable_if_t等降級到c ++ 11。 並相應地修改代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM