我有一些模板型別別,如 A、B、C,如下所示:
template < typename T >
class A{};
template < typename T >
class B{};
template < typename T >
class C{};
現在我想要一個函式,它通常接受任何型別,如:
template < typename T>
void Func()
{
std::cout << "Default " << __PRETTY_FUNCTION__ << std::endl;
}
現在我想專門化該函式以僅接受給定模板類之一,例如:
template < typename T>
void Func<A<T>>()
{
std::cout << "All A Types " << __PRETTY_FUNCTION__ << std::endl;
}
這是不允許的,因為它只是部分專業化。行。
我認為concept可能會有所幫助,但感覺我想得太復雜了。我的解決方案是:
template < typename T, template <typename > typename OUTER >
bool Check;
template < typename INNER, template < typename > typename OUTER, template < typename> typename T>
constexpr bool Check< T<INNER>, OUTER > = std::is_same_v< OUTER<INNER>, T<INNER>>;
template < typename T >
concept IsA = Check< T, A >;
template < typename T >
concept IsB = Check< T, B >;
template < IsA T >
void Func()
{
std::cout << "All A Types " << __PRETTY_FUNCTION__ << std::endl;
}
template < IsB T >
void Func()
{
std::cout << "All B Types " << __PRETTY_FUNCTION__ << std::endl;
}
int main()
{
Func<A<int>>();
Func<B<int>>();
Func<C<int>>();
}
我覺得有點復雜。可以簡化嗎?如果Check可以洗掉模板會很好。任何的想法?
在此處實時查看完整示例
uj5u.com熱心網友回復:
一種常見的解決方法是這樣的:
template <typename T>
struct FuncImpl {
static void Run() { std::cout << "Default"; }
};
template <typename T>
struct FuncImpl<A<T>> {
static void Run() { std::cout << "Specialized for A<T>"; }
};
template <typename T>
void Func() { FuncImpl<T>::Run(); }
函式模板不能部分特化,但類模板可以;所以我們只是將前者委托給后者。
uj5u.com熱心網友回復:
我覺得有點復雜。可以簡化嗎?如果可以洗掉檢查模板會很好。任何的想法?
事實上,您需要為每個類模板提供一個新概念。寫一個通用的、可復用的概念,使用起來不再復雜。
template <typename T, template <typename...> class TT>
constexpr bool is_instantiation_of_v = false;
template <template <typename...> class TT, typename... TS>
constexpr bool is_instantiation_of_v <TT<TS...>, TT> = true;
template <class C, template<typename...> class TT>
concept instantiation_of = is_instantiation_of_v<C, TT>;
與您的原理相同,除了檢查器可用于帶有任意數量型別引數的模板。同時,該概念接受相同的引數。第一個引數有特殊含義,隱式理解為簡寫語法中的約束模板引數。其余的(模板模板引數)必須明確給出。
如何使用?像這樣
template <instantiation_of<A> T>
int Func()
{
return 'A';
}
template <instantiation_of<B> T>
int Func()
{
return 'B';
}
有一個新的類模板來約束嗎?沒問題,這個概念不需要額外的樣板就可以作業。
template <instantiation_of<D> T>
int Func()
{
return 'D';
}
uj5u.com熱心網友回復:
OP寫道:
是的,如果可能的話,直接在函式模板引數中撰寫一些“即時”代碼會很好......
通常,要確定它是否是某個給定類模板的特化,我們會提前定義一個特征,然后檢查該型別是否滿足該特征。如果你不想提前定義任何東西,你必須找到一種方法來執行模板引數推導inline,這樣你就可以檢查它是否成功。在 C 20 中,這很簡單,但有點難看:
template <typename T>
void Func()
{
std::cout << "unconstrained" << std::endl;
}
template <typename T>
requires requires {
[]<typename U>(const A<U>&){}(std::declval<T>());
}
void Func()
{
std::cout << "constrained" << std::endl;
}
在這里,requires 子句檢查是否T可以系結到const A<U>&某些 deducible的型別引數U。你可以在這里看到這個例子:https ://godbolt.org/z/dTEbaaPvh
這讀起來并不令人愉快。如果您將多次使用此 hack,我認為最好只定義特征。我回答你的問題只是為了滿足你的好奇心,而不是推薦這種技術。
上面的版本將選擇受約束的版本,不僅當模板引數是 someA<U>時,而且當它可能是 cv-qualified、可能 ref-qualified 和可能公開派生自A<U>. 可以進行一些調整以使約束更加嚴格。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/412629.html
標籤:
下一篇:按位運算異或掩碼
