![](/img/trans.png)
[英]C++ derived template class is inheriting from template base class, cannot call base class constructor
[英]C++ Check if class derived from template base class; which has integral template parameters
有沒有一種方法可以測試Derived
的 class 是從BaseInterface
派生的,其中BaseInterface
的模板參數是無符號整數值? 我想將此檢查作為模板 std::enable_if 的一部分執行。 BaseInterface
有一個方法,該方法接受對字節塊的引用,該塊的大小將取決於OutputSize
模板參數。
template < size_t BlockSize, size_t OutputSize >
class BaseInterface {
public:
const static size_t BLOCK_SIZE = BlockSize;
const static size_t OUTPUT_SIZE = OutputSize;
using Output = uint8_t[ OutputSize ];
virtual ~BaseInterface() = default;
virtual void update( uint8_t*, size_t ) = 0;
virtual void getOutput( Output& ) = 0;
};
class Derived : public BaseInterface< 64, 16 > {
public:
...
};
我看到有評論提到可以這樣做,但它會比通常的 std::is_base_of 或 std::derived_from 更復雜。 當然,我還沒有找到這種“更復雜的方式”的任何實例。
因為模板參數不是類型,而是無符號整數值,所以這些都不起作用。 我想我最感興趣的是接口是否存在於通過模板傳入的 class 中。 我總是可以檢查每個方法,typedef 和常量。 這可能會很煩人......因此,如果有更好的方法可以做到這一點,請隨時說出來。
template < typename ImplementedInterface,
typename = typename std::enable_if<
... other checks here ...
is_derived< Derived, Base ??? >
>::type >
void method( ... input here ... ) {
ImplementedInterface ii;
ImplementedInterface::Output out;
ii.update( ... );
ii.output( out );
}
同時,我將弄清楚檢查派生的 class 以獲取所需接口需要做多少工作。
檢測基本 class 模板實際上很容易,只要它明確且可訪問,例如:
template <size_t BlockSize, size_t OutputSize>
size_t get_block_size(const BaseInterface<BlockSize, OutputSize>&) {
return BlockSize;
}
get_block_size(Derived{}); // returns 64
這是因為雖然模板參數推導通常需要“精確匹配”,但當參數類型是派生的 class 類型時,此規則有一個例外。 在這種情況下,如果派生的 class 類型無法成功推導模板參數,則編譯器會嘗試使用參數類型的基本 class (繼續向上 inheritance 層次結構),直到推導成功。 1
您可以使用此功能輕松構建所需的類型特征。
1此規則僅適用於參數類型為simple-template-id或指向simple-template-id 的指針; C++20 [temp.deduct.call]/4.3。
免責聲明:這個答案主要基於@Jarod42 對另一個問題的回答。
雖然@Brian 的答案可能適用於您的特定情況,但在您需要使用派生類型做更復雜的事情的情況下(例如,將其向上轉換為 BaseType<64, 16> 不是一個選項,可能是因為您需要在某處保持類型一致性),那么這是一個更通用的解決方案:
template<typename T>
struct is_derived_from_base_interface {
private:
template<size_t S1, size_t S2>
static decltype(static_cast<const BaseInterface<S1, S2>&>(std::declval<T>()), std::true_type{})
test(const BaseInterface<S1, S2>&);
static std::false_type test(...);
public:
static constexpr bool value =
decltype(is_derived_from_base_interface::test(std::declval<T>()))::value;
};
int main() {
// prints 1, for true
std::cout << "Derived is derived from BaseInterface: " << is_derived_from_base_interface<Derived>::value << "\n";
// prints 0, for false
std::cout << "Derived is derived from BaseInterface: " << is_derived_from_base_interface<std::string>::value << "\n";
return 0;
}
您可以將它與std::enable_if
一起使用,如下所示:
template<typename T>
typename std::enable_if<is_derived_from_base_interface<T>::value>::type my_function(T&& arg) {
// Do something
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.