比方說,我有一個簡單地爲任何類型T執行加法的類。我想添加一個可選範圍檢查(基於類型爲bool的模板參數),它將檢查結果的加法屬於給定範圍,否則會拋出。 這樣做的一種方法是將類的所有基礎知識包裝在基類中,然後專門研究布爾模板參數。喜歡的東西:基於模板參數的可選範圍檢查
// The base class; holds a starting value to add to and a maximum value
template<typename T>
class DummyImpl
{
private:
T mval, mmax;
public:
constexpr explicit DummyImpl(T x, T max_x) noexcept
: mval{x}, mmax{max_x}
{};
// base class; use a virtual destructor
virtual ~DummyImpl() {};
T max() const noexcept {return mmax;}
T val() const noexcept {return mval;}
};
// The "real" class; parameter B denotes if we want (or not)
// a range check
template<typename T, bool B>
class Dummy : DummyImpl<T> {};
// Specialize: we do want range check; if sum not in range
// throw.
template<typename T>
class Dummy<T, true> : DummyImpl<T>
{
public:
explicit Dummy(T x, T max_x) noexcept : DummyImpl<T>(x, max_x) {};
T add(T x) const noexcept(!true)
{
T ret_val = x + DummyImpl<T>::val();
if (ret_val < 0 || ret_val > DummyImpl<T>::max()) {
throw 1;
}
return ret_val;
}
};
// Specialize for no range check.
template<typename T>
class Dummy<T, false> : DummyImpl<T>
{
public:
explicit Dummy(T x, T max_x) noexcept : DummyImpl<T>(x, max_x) {};
T add(T x) const noexcept(!false)
{
return x + DummyImpl<T>::val();
}
};
現在,用戶可以編寫類似的代碼:
int main()
{
Dummy<float,false> d(0, 1000); //no range check; never throw
std::cout <<"\nAdding 156.7 gives " << d.add(156.7);
std::cout <<"\nAdding 3156.7 gives " << d.add(3156.7);
std::cout <<"\n";
return 0;
}
是否有這樣做,而不使用繼承的方式嗎?我假設使用嵌套類會更高效,但下面的代碼 不能編譯。
template<typename T, bool RC>
class Dummy
{
private:
T mval, mmax;
// parameter S is only used to enable partial specialization on
// parameter I
template<bool I, typename S> struct add_impl {};
template<typename S> struct add_impl<true, S>
{
T operator()(T x) const noexcept(!true)
{
T ret_val = x + mval;
if (ret_val < 0 || ret_val > mmax) {throw 1;}
return ret_val;
}
};
template<typename S> struct add_impl<false, S>
{
T operator()(T x) const noexcept(!false)
{
return x + mval_ref;
}
};
public:
constexpr explicit Dummy(T x, T max_x) noexcept
: mval{x}, mmax{max_x}
{};
void bar() const { std::cout << "\nin Base."; }
T max() const noexcept {return mmax;}
T val() const noexcept {return mval;}
T add(T x) const noexcept(!RC)
{
return add_impl<RC, T>()(x);
}
};
int main()
{
Dummy<float,false> d(0, 1000);
std::cout <<"\nAdding 156.7 gives " << d.add(156.7);
std::cout <<"\nAdding 3156.7 gives " << d.add(3156.7);
std::cout <<"\n";
return 0;
}
它失敗(以g ++)的錯誤消息:
error: invalid use of non-static data member ‘Dummy<float, false>::mval’
有沒有解決這個的方法嗎?如果是這樣,它比第一種解決方案更有效嗎?嵌套類是否將尺寸添加到Dummy的任何實例?有沒有更優雅的設計/實施?
如何根據參數修改模板代碼:查找SFINAE或模板特化。但是這對你的用例真的有用嗎?有一個bool參數爲false,它不會說什麼錯誤會導致代碼不可讀。 – Klaus