我寫這封信旨在拍攝隨機三維向量類,但我用幾個幾何庫在我的項目(一個包含在三維仿真,一個納入分析框架,其中一個是沒有包含在1 GB以上的框架中......)。每個圖書館都有自己的向量的定義,與同樣的方法不同的名稱,例如具有的getX()的getX(),獲取(0)...拿到第一笛卡爾座標。但是有時會採用通用的命名約定,並且一些方法名稱在兩個或多個庫中是相同的。
我當然希望使用此代碼對任何這些載體的,所以我實現了一個模板類。問題如下:如何使我的代碼適應所有這些方法名稱,而無需爲每個實現專門設計我的類(某些方法名稱相同)?
我設法編寫使用的方法或其他,我現在想推廣到任意數量方法的類。一些東西,說:「如果你有方法1,使用此實現,如果你有方法2,使用另一種,...如果你沒有,那麼編譯錯誤」。模板類取決於模板參數方法
目前該類看起來像(縮小到部分拍攝隨機方向):
// First some templates to test the presence of some methods
namespace detail_rand {
// test if a class contains the "setRThetaPhi" method
template<class T>
static auto test_setRThetaPhi(int) ->
decltype(void(std::declval<T>().setRThetaPhi(0.,0.,0.)),
std::true_type{});
template<class T>
static auto test_setRThetaPhi(float)->std::false_type;
}
// true_type if the class contains the "setRThetaPhi" method
template<class T>
struct has_setRThetaPhi : decltype(detail_rand::test_setRThetaPhi<T>(0)) {};
// The actual class
template<class vector>
class Random
{
// everything is static for easy use, might change later
private:
Random() = delete;
Random(Random&) = delete;
// the distribution, random generator and its seed
static decltype(std::chrono::high_resolution_clock::now().time_since_epoch().count()) theSeed;
static std::default_random_engine theGenerator;
static std::uniform_real_distribution<double> uniform_real_distro;
// Shoot a direction, the actual implementation is at the end of the file
private: // the different implementations
static const vector Dir_impl(std::true_type const &);
static const vector Dir_impl(std::false_type const &);
public: // the wrapper around the implementations
inline static const vector Direction() {
return Dir_impl(has_setRThetaPhi<vector>());
}
};
/// initialisation of members (static but template so in header)
// the seed is not of cryptographic quality but here it's not relevant
template<class vector>
decltype(std::chrono::high_resolution_clock::now().time_since_epoch().count())
Random<vector>::theSeed =
std::chrono::high_resolution_clock::now().time_since_epoch().count();
template<class vector>
std::default_random_engine Random<vector>::theGenerator(theSeed);
template<class vector>
std::uniform_real_distribution<double> Random<vector>::uniform_real_distro(0.,1.);
/// Implementation of method depending on the actual type of vector
// Here I use the "setRThetaPhi" method
template<class vector>
const vector Random<vector>::Dir_impl(std::true_type const &)
{
vector v;
v.setRThetaPhi(1.,
std::acos(1.-2.*uniform_real_distro(theGenerator)),
TwoPi()*uniform_real_distro(theGenerator));
return std::move(v);
}
// Here I use as a default the "SetMagThetaPhi" method
// but I would like to test before if I really have this method,
// and define a default implementation ending in a compilation error
// (through static_assert probably)
template<class vector>
const vector Random<vector>::Dir_impl(std::false_type const &)
{
vector v;
v.SetMagThetaPhi(1.,
std::acos(1.-2.*uniform_real_distro(theGenerator)),
TwoPi()*uniform_real_distro(theGenerator));
return std::move(v);
}
真棒回答!我希望我早點找到你的(順便說一下)文章,我會節省幾個小時。我明天一定會看你的視頻! – gaFF