[英]Accessing members of base classes in the derived class through runtime indexing
考慮以下代碼
#include <array>
#include <iostream>
template <std::size_t> struct base {
std::size_t value;
};
struct derived: base<0>, base<1> {
using pointer_type = std::size_t derived::*;
static constexpr std::array<pointer_type, 2> members{{
&derived::base<0>::value,
&derived::base<1>::value
}};
constexpr std::size_t& operator[](std::size_t i) noexcept {
return this->*(members[i]);
}
constexpr const std::size_t& operator[](std::size_t i) const noexcept {
return this->*(members[i]);
}
};
int main(int, char**) {
derived x{42, 84};
std::cout << sizeof(base<0>) + sizeof(base<1>) << " " << sizeof(derived);
std::cout << std::endl;
std::cout << x[0] << " " << x[1];
std::cout << std::endl;
return 0;
}
它創建了一個帶有數據成員value
的模板化結構base
,以及一個derived
它的幾個特化繼承而來的結構。 我想根據運行時提供的索引訪問一個或另一個基礎 class 的value
。 提供的代碼似乎沒有實現這一點,並且總是返回第一個base
的value
。
我想實現它:
base
的代碼derived
從base
類繼承的方式sizeof(derived)
(技巧應該是constexpr/static
)reinterpret_cast
)O(1)
復雜度換句話說,我不想改變的代碼布局應該是:
#include <array>
#include <iostream>
template <std::size_t> struct base {
std::size_t value;
};
struct derived: base<0>, base<1> {
/* things can be added here */
constexpr std::size_t& operator[](std::size_t i) noexcept {
/* things can be added here */
}
constexpr const std::size_t& operator[](std::size_t i) const noexcept {
/* things can be added here */
}
};
int main(int, char**) {
derived x{42, 84};
std::cout << sizeof(base<0>) + sizeof(base<1>) << " " << sizeof(derived);
std::cout << std::endl;
std::cout << x[0] << " " << x[1];
std::cout << std::endl;
return 0;
}
問題:為什么當前的技巧不起作用,有沒有辦法讓它起作用?
編輯:似乎是一個 GCC 錯誤。 我在這里報告了。 在此處與 clang 進行比較。
額外的問題(語言律師) :它是 GCC 錯誤,還是根據 C++17 標准的未定義行為?
這看起來像一個 GCC 錯誤。 您的原始代碼生成預期的 output 和 Clang。
我能夠找到的 GCC 的一種解決方法是將members
變成 static 成員 function:
static constexpr array_type members() noexcept {
return {&base<0>::value, &base<1>::value};
}
constexpr std::size_t& operator[](std::size_t i) noexcept {
return this->*members()[i];
}
如評論中所述,很可能是 GCC 錯誤。 盡管如此,有一個有趣的解決方法是使用std::tuple
而不是std::array
:
#include <tuple>
#include <array>
#include <iostream>
template <std::size_t> struct base {
std::size_t value;
};
template<class T, class Tuple, std::size_t... Indx>
constexpr auto to_arr_h(const T& val, const Tuple& t, std::index_sequence<Indx...>) {
return std::array<std::size_t, sizeof...(Indx)>{val.*(std::get<Indx>(t))...};
}
template<class T, class... Ts>
constexpr auto to_arr(const T& val, const std::tuple<Ts...>& t) {
return to_arr_h(val, t, std::make_index_sequence<sizeof...(Ts)>{});
}
struct derived: base<0>, base<1> {
static constexpr auto members = std::make_tuple(&base<0>::value, &base<1>::value);
constexpr std::size_t& operator[](std::size_t i) noexcept {
return to_arr(*this, members)[i];
}
constexpr const std::size_t& operator[](std::size_t i) const noexcept {
return to_arr(*this, members)[i];
}
};
int main(int, char**) {
derived x{42, 84};
std::cout << sizeof(base<0>) + sizeof(base<1>) << " " << sizeof(derived);
std::cout << std::endl;
std::cout << x[0] << " " << x[1];
std::cout << std::endl;
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.