你可以做的玉米稈建議,並使用std::begin
和std::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。並相應地調整代碼。
你不能。但是,您可以使'fun1()'成爲一個獨立的函數,它接受參數並完成必要的工作。類似於['std :: begin()'](http://en.cppreference.com/w/cpp/iterator/begin)是一個將容器作爲參數的獨立函數,然後將委託(如'std :: vector'),或者委託給其他可以返回正確值的東西(例如像'int [5]'這樣的數組,它沒有'.begin()')。 – Cornstalks
如何判斷一個容器是否可以通過模板特化來調用.beign()? – user3230380