問題
這里有一些代碼
struct Base
{
int SomeMethod(const Base&);
template <class T> int SomeMethod(const T&);
};
template <class Tag> struct Derived : Base
{
using Base::SomeMethod;
int SomeMethod(const Derived&);
template <class OtherTag> std::enable_if_t<!std::is_same_v<Tag, OtherTag>> SomeMethod(Derived<OtherTag>) = delete;
};
struct tag {};
struct another_tag {};
struct ImplicitOpToAnotherTagInstantiation { operator Derived<another_tag>() const; };
是否有一些東西(Derived::SomeMethod多載)我可以在Derived不觸及的情況下寫入Base,這會導致下一個代碼中的編譯器錯誤?
Derived<tag>{}.SomeMethod(ImplicitOpToAnotherTagInstantiation {});
下一個代碼應該是正確的
struct ImplicitOpToBase { operator Base() const; };
Derived<tag>{}.SomeMethod(Derived<tag>{});
Derived<tag>{}.SomeMethod(Base{});
Derived<tag>{}.SomeMethod(ImplicitOpToBase{});
// Derived<tag>{}.SomeMethod(Derived<another_tag>{}); compiler error!
我試過什么
- 第一個想法是做這樣的事情:
template <class Tag> struct Derived : Base
{
using Base::SomeMethod;
int SomeMethod(const Derived&);
template <class OtherTag> std::enable_if_t<!std::is_same_v<Tag, OtherTag>> SomeMethod(Derived<OtherTag>) = delete;
template <class T, class OtherTag> std::enable_if_t<!std::is_same<Tag, OtherTag> && std::is_convertible<Tag, Derived<OtherTag>>> SomeMethod(T) = delete;
};
但它不起作用,因為編譯器無法推斷OtherTag,沒有像這樣的顯式實體化
Derived<tag>{}.SomeMethod<ImplicitOpToAnotherTagInstantiation, another_tag>(); // error: deleted function!
- 第二個想法:
template <class Tag> struct Derived : Base
{
using Base::SomeMethod;
int SomeMethod(const Derived&);
template <class OtherTag> std::enable_if_t<!std::is_same_v<Tag, OtherTag>> SomeMethod(Derived<OtherTag>) = delete;
template <class T> std::enable_if_t<!std::is_same<T, Derived> && std::is_convertible<T, Base>> SomeMethod(T) = delete;
};
但是下一個代碼會導致編譯器錯誤,什么時候不應該:
Derived<tag>{}.SomeMethod(ImplicitOpToBase{});
主要用途
std::string我正在嘗試為where Baseis std::string, Derivedis my TaggedString, SomeMethodis創建某種強型別定義std::string::assign。我想禁用assign其他標簽型別的方法,我在問題中解釋了一些困難。為了讀者,我忽略了一個事實,即TaggedString隱式轉換為std::string_view.
template <class Tag> struct TaggedString : std::string
{
using std::string::assign;
TaggedString& assign(const TaggedString& other) { std::string::assign(other); return *this; }
template <class OtherTag> std::enable_if_t<!std::is_same_v<Tag, OtherTag>> assign(TaggedString<OtherTag>) = delete;
};
這里有一些東西可以玩。
uj5u.com熱心網友回復:
不,有無限的可能轉換,甚至無限的轉換到Derived<SomeUnknownType>. 您的編譯器無法測驗所有可能的型別 T 以查看是否ImplicitOpToAnotherTagInstantiation可以轉換為Derived<T>.
如果你提供它,它可以測驗一個有限集。但你只有tag一個要排除的型別。無限的型別集減去一個型別仍然是無限的型別集。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/428012.html
上一篇:使用包裝器確定函式時間
