SFINAE将实例化类型限制为std::chrono::duration类型



我想做一些类似的事情

template <typename T>
class TemporalAlarmDelay<T, std::enable_if<std::is_base_of<std::chrono::duration< , >, T>::value, T>::type>
{
public:
explicit TemporalAlarmDelay(T delay)
: mDelay(delay)
{
}
private:
T mDelay;
std::chrono::steady_clock::time_point mTriggerTime;
};

int main(int argc, char** args)
{
TemporalAlarmDelay<std::chrono::nanoseconds> nanosecondDelay;   // this should work
TemporalAlarmDelay<std::chrono::milliseconds> millisecondDelay; // this should work 
TemporalAlarmDelay<std::chrono::seconds> secondDelay;           // this should work
TemporalAlarmDelay<int> failDelay;                              // fail to instantiate
}

其目的是限制std::chrono::duration的类型(例如std::chrono::millisecondsstd::chrono::seconds)。对此,最好的方法是什么?根据我的例子,我认为我可以使用std::is_base_of,但我现在意识到辅助类型(例如std::chrono::millisecondsstd::chrono::seconds等)不使用继承-derrr,这是一个多么愚蠢的想法。

对于问题的最简单解决方案。。。

#include <chrono>
class TemporalAlarmDelay
{
public:
explicit TemporalAlarmDelay(std::chrono::steady_clock::duration delay)
: mDelay(delay)
{
}
private:
std::chrono::steady_clock::duration   mDelay;
std::chrono::steady_clock::time_point mTriggerTime;
};

int main()
{
using namespace std::chrono_literals;
TemporalAlarmDelay nanosecondDelay{1ns};   // this works
TemporalAlarmDelay millisecondDelay{1ms};  // this works
TemporalAlarmDelay secondDelay{1s};        // this works
TemporalAlarmDelay failDelay{1};           // compile-time error
}

您可以使用模板专业化:

template <typename T>
class TemporalAlarmDelay
{
~TemporalAlarmDelay() = delete; // prevent instantiation
};
template <typename R, typename P>
class TemporalAlarmDelay<std::chrono::duration<R, P>>
{
// your code
};

@Jarod42建议你甚至可以逃脱:

template <typename> class TemporalAlarmDelay;

而不是上面的前四行。

您可以创建特征:

template <typename T> struct is_chrono_duration : std::false_type {};
template <typename R, typename P>
struct is_chrono_duration<std::chrono::duration<R, P>> : std::true_type {};

然后:

template <typename T>
class TemporalAlarmDelay
{
static_assert(is_chrono_duration<T>::value, "!");
// your code
};

从Jarod42的is_chrono_duration(好吧……老实说,复制它)中获得灵感,这是一种可能的基于SFINAE的(超过默认布尔值)解决方案

template <typename T, bool = is_chrono_duration<T>::value>
class TmpAlrD;
template <typename T>
class TmpAlrD<T, true>
{
// ...
};

以下是的完整编译示例

#include <chrono>
#include <type_traits>
template <typename>
struct is_chrono_duration : std::false_type
{ };
template <typename R, typename P>
struct is_chrono_duration<std::chrono::duration<R, P>> : std::true_type
{ };
template <typename T, bool = is_chrono_duration<T>::value>
class TmpAlrD;
template <typename T>
class TmpAlrD<T, true>
{
public:
explicit TmpAlrD(T delay = T{}) : mDelay(delay)
{ }
private:
T mDelay;
std::chrono::steady_clock::time_point mTriggerTime;
};
int main ()
{
TmpAlrD<std::chrono::nanoseconds>  nsDelay; // compile
TmpAlrD<std::chrono::milliseconds> msDelay; // compile 
TmpAlrD<std::chrono::seconds>      sDelay;  // compile
//TemporalAlarmDelay<int>                   // compilation error     
}

相关内容

最新更新