2017-05-04 53 views
0

我正在實施的東西通過使用C++,我有一個類型的索引集羣,它包括兩個成員:一個是整數,另一個是結構,像這樣:如何添加成員函數的內置類型,如整數在C++

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

又來了一個要求,我想補充一個共同的功能(假設,將其命名爲FUN1())這兩種類型,因爲我想通過他們在一個模板函數,它將調用FUN1 (),很容易實現這個爲IndexB_t,但它困惑我爲IndexA_t,我怎麼可以引入一個整數(內置)類型的函數成員?我必須實現一個模擬int類的類嗎?它真的需要很多不必要的工作(很多操作員......),還有其他方法嗎?

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

+1

你不能。但是,您可以使'fun1()'成爲一個獨立的函數,它接受參數並完成必要的工作。類似於['std :: begin()'](http://en.cppreference.com/w/cpp/iterator/begin)是一個將容器作爲參數的獨立函數,然後將委託(如'std :: vector'),或者委託給其他可以返回正確值的東西(例如像'int [5]'這樣的數組,它沒有'.begin()')。 – Cornstalks

+0

如何判斷一個容器是否可以通過模板特化來調用.beign()? – user3230380

回答

0

你可以做的玉米稈建議,並使用std::beginstd::end採用相同的技術。它爲定義成員函數的對象提供了過載,並且爲進一步使用該函數的類型(在這種情況下爲數組)提供了重載。

在下面的設計示例中,我們有一個免費函數getval,它提供了定義getval成員函數的類型的重載,使用尾隨返回類型來激活SFINAE。然後對於其他類型,它使用類型特徵來確保只有整數類型被允許,其他所有類型被拒絕,再次使用SFINAE通過enable_if

這個例子是做作和僅用於展示的技術,您可以使用來實現你需要的功能爲準(這個問題沒有詳細說明是什麼,所以我不得不使用許可證)。在下面的例子中,通過向IndexB_t類添加一個int轉換運算符來實現相同的效果顯然會更容易,但這不是重點。

#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。並相應地調整代碼。

0

這是不是太難硬件實現類似行爲像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); 
} 
+0

是的,這是可能的,但我想知道是否有其他方式,我真的不想維護一個自定義的Int類。 :( – user3230380

相關問題