簡體   English   中英

是否可以使用“if constexpr”來確定是否可以使用特定類型參數實例化模板函數?

[英]Is it possible to use 'if constexpr' to determine if a template function could be instantiated with a particular type parameter?

假設存在以下代碼:

class Foo {
 public:
    void foo() const { std::cout << "foo" << std::endl; }
};

class Bar {
 public:
    void bar() const { std::cout << "bar" << std::endl; }
}; 

template <typename T>
void DoFoo(const T& f) {
    f.foo();
}

我想寫一個這樣的函數:

template <typename T>
void DoFooIfPossible() {
    if constexpr (/* DoFoo<T>(T()) would compile */) {
        DoFoo(T());
    } else {
        std::cout << "[not possible]" << std::endl;
    }
}

以便:

int main() {
    DoFooIfPossible<Foo>();
    DoFooIfPossible<Bar>();
}

編譯和打印:

foo
[not possible]

我知道對於這個特定的示例,我可以通過檢測DoFoo使用的成員函數的存在以下列方式實現它:

template <typename T, typename = void>
struct IsFooPossible : std::false_type {};

template <typename T>
struct IsFooPossible<
    T, std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::foo)>>> 
    : std::true_type {};

template <typename T>
void DoFooIfPossible() {
    if constexpr (IsFooPossible<T>::value) {
        DoFoo(T());
    } else {
        std::cout << "[not possible]" << std::endl;
    }
}

但是,我在這里要問的問題是:我可以在DoFoo的實現做任何假設的情況下實現它嗎? .

在現實世界的場景中, DoFoo可能是我不擁有的庫函數。 它可能會在其模板參數類型T上放置許多不同的條件,並且這些條件可能會隨着時間而改變。 因此,在我的代碼中的enable_if表達式中復制這些條件並不是一個可行的解決方案。

我想知道是否有可能以直接測試DoFoo<T>是否可以實例化的方式編寫我的if constexpr表達式,而無需對DoFoo的實現有任何特殊了解,也無需修改DoFoo

我正在嘗試在 C++17 中做到這一點,所以如果 C++20 中有一些東西可以處理這個問題,那會很有趣,但不會解決我的問題。

(另請注意,為了創建一個最小的示例,我假設T是默認可構造的。我並不真正關心DoFoo(T())T()部分——我正在嘗試確定如果DoFoo<T>完全可以實例化。)

最終的解決方案是 C++20 concept ,因為老式的 SFINAE 方法有它們的警告。 但是,仍然有編譯器錯誤可能會追捕您。 您可以使用requires子句作為最終可以評估constexpr bool的內聯概念:

if constexpr(
    requires {
        /*do your test declaration s*/
    }
)//...rest

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM