buz*_*sin 1 c++ templates sfinae class-template c++17
考虑以下场景:
template <
typename T,
bool B = std::is_default_constructible_v<T>>
class toy_example;
template<typename T>
class toy_example<T, true>
{
public:
toy_example() = default; // e.g. for default constructible types
toy_example(const T& value);
public:
void monomorphic(T);
private:
T m_value;
};
template<typename T>
class toy_example<T, false>
{
public:
toy_example() = delete; // e.g. for non-default constructible types
toy_example(const T& value); // Repeated declaration
public:
void monomorphic(T); // Repeated declaration
private:
T m_value;
};
// Implementation
template<typename T>
toy_example<T, true>::toy_example(const T& value) : m_value(value) {}
// (Unnecessary?) Repetition
template<typename T>
toy_example<T, false>::toy_example(const T& value) : m_value(value) {}
template<typename T>
toy_example<T, true>::monomorphic(T)
{
std::cout << "Behaviour is the same despite specialisation.\n";
// (P.S) - This is intended behaviour
}
// (Unnecessary?) Repetition
template<typename T>
toy_example<T, false>::monomorphic(T)
{
std::cout << "Behaviour is the same despite specialisation.\n";
// (P.S) - This is intended behaviour
}
Run Code Online (Sandbox Code Playgroud)
monomorphic如何通过为我想要以相同方式运行的函数(在本例中为初始化构造函数和函数)提供单个定义来为此类提供更紧凑的定义?
我这样做的动机是,在我的代码库中,代码monomorphic(T)有点冗长,我宁愿不要不必要地重复它。
我知道解决方案可能涉及使用某种基类,但我不确定如何解决这个问题。
如何通过为我想要以相同方式运行的函数(在本例中为初始化构造函数和单态函数)提供单个定义来为此类提供更紧凑的定义?
由于您使用的是c++17,我将使用该if constexpr功能,通过该功能可以将两种实现保持在同一函数体中。
此外,对于同一类中的每种情况,可以对默认构造函数(以及其他公共代码)进行 SFINAEd 处理。
沿着这些思路。
class ExampleClass
{
public:
template<typename U = T>
ExampleClass(std::enable_if_t<std::is_default_constructible_v<U>>* = 0)
{} // enabled only for default constructible types
template<typename U = T>
ExampleClass(
std::enable_if_t<!std::is_default_constructible_v<U>>* = 0
) = delete; // For non-default constructible types
ExampleClass(const T& value)
: m_value{ value } {}
public:
void monomorphic()
{
if constexpr (std::is_default_constructible_v<T>)
{
std::cout << "default_constructible Impli\n";
}
else
{
std::cout << "Non-default_constructible Impli\n";
}
}
private:
T m_value;
};
Run Code Online (Sandbox Code Playgroud)
或者,您显然可以在 中拥有通用实现,Base并且派生类(即启用/禁用std::is_default_constructible_v)可以具有专门化的monomorphic()功能,如下所示:
// Common base class
template<typename T> class Base
{
public:
template<typename U = T>
Base(std::enable_if_t<std::is_default_constructible_v<U>>* = 0)
{} // enabled only for default constructible types
template<typename U = T>
Base(std::enable_if_t<!std::is_default_constructible_v<U>>* = 0)
= delete; // for non default constructible types
Base(const T& value)
: m_value{ value } {}
private:
T m_value;
};
template <typename T, typename Enable = void> class Derived;
// specialization for true case
template<typename T>
class Derived<T,
std::enable_if_t<std::is_default_constructible_v<T>>>
: public Base<T>
{
public:
Derived() = default;
using Base<T>::Base;
void monomorphic(){ std::cout << "default_constructible Impli\n"; }
};
// specialization for false case
template<typename T>
class Derived<T,
std::enable_if_t<!std::is_default_constructible_v<T>>>
: public Base<T>
{
public:
using Base<T>::Base;
void monomorphic() { std::cout << "Non-default_constructible Impli\n"; }
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
80 次 |
| 最近记录: |