我希望我的類對沒有 constexpr 建構式的型別使用另一種實作。
像這樣:
template <typename A>
class foo
{
public:
// if A has constexpr constructor
constexpr foo() :_flag(true) { _data._a = A(); }
// else
constexpr foo() : _flag(false) { _data.x = 0; }
~foo(){}
bool _flag;
union _data_t
{
_data_t() {} // nothing, because it's just an example
~_data_t() {}
A _a;
int x;
}_data;
};
為了實作標題所說的,我試試這個:
template<typename _t, _t = _t()>
constexpr bool f()
{
return true;
}
template<typename _t>
constexpr bool f()
{
return false;
}
它適用于沒有 constexpr 建構式的型別。但對于其他型別,它會導致多載不明確的編譯錯誤。
那么我該如何檢查?
uj5u.com熱心網友回復:
我想您可以將 SFINAE 與逗號運算子的功能一起使用
按照你的想法,你可以重寫你的f()
功能如下
template <typename T, int = (T{}, 0)>
constexpr bool f (int)
{ return true; }
template <typename>
constexpr bool f (long)
{ return false; }
注意訣竅:int = (T{}, 0)
對于第二個模板引數
僅當可以構造 constexpr (因為是模板引數的引數f()
)時才啟用這種方式(逗號運算子的功能),否則 SFINAE 會洗掉.T{}
(T{}, 0)
f()
并觀察第一個版本的f()
接收一個未使用int
的,第二個接收一個long
。這樣,第一個版本是首選的,如果可用,f()
使用int
;呼叫 當第一個不可用時(當第一個模板引數不是 constexpr 默認可構造時),選擇第二個作為解決方案總比沒有好。
現在您可以構造兩個模板建構式foo
,您可以根據模板引數T
(默認為A
)是或不是 constexpr 可構造的事實來選擇啟用/禁用
template <typename T = A,
std::enable_if_t<f<T>(0), std::nullptr_t> = nullptr>
constexpr foo() { std::cout << "constexpr" << std::endl; }
template <typename T = A,
std::enable_if_t<not f<T>(0), std::nullptr_t> = nullptr>
constexpr foo() { std::cout << "not constexpr" << std::endl; }
以下是完整的編譯示例(C 14 或更高版本,但您可以針對 C 11 進行修改):
#include <iostream>
#include <type_traits>
template <typename T, int = (T{}, 0)>
constexpr bool f (int)
{ return true; }
template <typename>
constexpr bool f (long)
{ return false; }
template <typename A>
struct foo
{
template <typename T = A,
std::enable_if_t<f<T>(0), std::nullptr_t> = nullptr>
constexpr foo() { std::cout << "constexpr" << std::endl; }
template <typename T = A,
std::enable_if_t<not f<T>(0), std::nullptr_t> = nullptr>
constexpr foo() { std::cout << "not constexpr" << std::endl; }
};
struct X1 { constexpr X1 () {} };
struct X2 { X2 () {} };
int main()
{
foo<X1> f1; // print "constexpr"
foo<X2> f2; // print "not constexpr"
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/469974.html
上一篇:使用std::for_each在std::set上系結成員函式,代碼無法編譯
下一篇:bash腳本中的遞回awk