C++ 模板化默认构造函数
我希望在编译时通过模板参数切换默认构造函数的定义。我可以让它为转换构造函数编译OK,但尝试将该方法用于默认构造函数是否为默认构造函数——如果在特定模板参数的情况下,生成的类可能是POD,则很有用,但在另一种情况下,它不能——但这样做时会出现编译器错误。除了专门化模板和复制所有相同的代码之外,还有什么方法可以做到这一点吗?以下是我尝试的简化版本:C++ 模板化默认构造函数,c++,templates,sfinae,C++,Templates,Sfinae,我希望在编译时通过模板参数切换默认构造函数的定义。我可以让它为转换构造函数编译OK,但尝试将该方法用于默认构造函数是否为默认构造函数——如果在特定模板参数的情况下,生成的类可能是POD,则很有用,但在另一种情况下,它不能——但这样做时会出现编译器错误。除了专门化模板和复制所有相同的代码之外,还有什么方法可以做到这一点吗?以下是我尝试的简化版本: #include<type_traits> // for enable_if template <bool MyParamete
#include<type_traits> // for enable_if
template <bool MyParameter>
class Demonstration
{
public:
//trivial copy, move constructors/assignment, and trivial destructor
constexpr Demonstration(Demonstration const &) = default;
constexpr Demonstration(Demonstration &&) = default;
Demonstration & operator= (Demonstration const &) = default;
Demonstration & operator= (Demonstration &&) = default;
~Demonstration() = default;
// this one gives "error: a template cannot be defauled"
template <bool Dummy=MyParameter, typename std::enable_if< Dummy , bool >::type=true >
Demonstration() = default;
// ok
template <bool Dummy=MyParameter, typename std::enable_if< !Dummy , bool >::type=false >
Demonstration() : myValue(0) {}
// ok
template <bool Dummy=MyParameter, typename std::enable_if< Dummy , bool >::type=true >
explicit constexpr Demonstration(unsigned char toConvert)
: myValue ( toConvert )
{
}
// ok
template <bool Dummy=MyParameter, typename std::enable_if< !Dummy , bool >::type=false >
explicit constexpr Demonstration(unsigned char toConvert)
: myValue ( toConvert > 100 ? 0 : toConvert )
{
}
// a lot of functions that do not depend on parameter go here
protected:
private:
unsigned char myValue;
};
#包括//for enable_如果
模板
课堂演示
{
公众:
//普通复制、移动构造函数/赋值和普通析构函数
constexpr演示(演示const&)=默认值;
constexpr演示(演示&)=默认值;
演示和运算符=(演示常量&)=默认值;
演示和运算符=(演示和运算符)=默认值;
~display()=默认值;
//这一条给出了“错误:模板不能被破坏”
模板::type=true>
演示()=默认值;
//嗯
模板::type=false>
演示():myValue(0){}
//嗯
模板::type=true>
显式constexpr演示(无符号字符转换)
:myValue(toConvert)
{
}
//嗯
模板::type=false>
显式constexpr演示(无符号字符转换)
:myValue(toConvert>100?0:toConvert)
{
}
//许多不依赖于参数的函数都在这里
受保护的:
私人:
无符号字符myValue;
};
GCC投诉您的模板:
error: a template cannot be defaulted
Clang抱怨说:
error: only special member functions may be defaulted.
这似乎很公平。成员函数模板不是成员函数,
更不用说特别的了
当p
为真时,您希望演示
为POD,否则
不一定如此
一个可能的解决方案是完全委托POD ness的参数化
到基本模板的专门化base
,并具有
演示
继承基础
。下面是一个例子:
#include<type_traits>
template<bool Param = true>
struct base // is POD
{
base() = default;
explicit constexpr base(unsigned char ch)
: _val(ch){}
unsigned char _val;
};
template<>
struct base<false> // is not POD
{
base() = default;
explicit constexpr base(unsigned char ch)
: _val(ch > 100 ? 0 : ch){}
unsigned char _val = 0;
};
template <bool MyParameter>
class Demonstration : private base<MyParameter>
{
public:
Demonstration() = default;
//trivial copy, move constructors/assignment, and trivial destructor
constexpr Demonstration(Demonstration const &) = default;
constexpr Demonstration(Demonstration &&) = default;
Demonstration & operator= (Demonstration const &) = default;
Demonstration & operator= (Demonstration &&) = default;
~Demonstration() = default;
explicit constexpr Demonstration(unsigned char toConvert)
: base<MyParameter>(toConvert)
{
}
char myValue() const {
return base<MyParameter>::_val;
}
};
#include <iostream>
using namespace std;
int main()
{
cout << "is_pod<base<true>>::value = "
<< is_pod<Demonstration<true>>::value << endl;
cout << "is_pod<base<false>>::value = "
<< is_pod<Demonstration<false>>::value << endl;
cout << "is_pod<Demonstration<true>>::value = "
<< is_pod<Demonstration<true>>::value << endl;
cout << "is_pod<Demonstration<false>>::value = "
<< is_pod<Demonstration<false>>::value << endl;
Demonstration<true> d_true(1);
Demonstration<false> d_false(101);
std::cout << "(int)Demonstration<true>(1).myValue() = "
<< (int)d_true.myValue() << endl;
std::cout << "(int)Demonstration<false>(101).myValue() = "
<< (int)d_false.myValue() << endl;
return 0;
}
#包括
模板
结构基//是POD
{
base()=默认值;
显式constexpr基(无符号字符ch)
:_val(ch){}
无符号字符;
};
模板
结构基//不是POD
{
base()=默认值;
显式constexpr基(无符号字符ch)
:_val(ch>100?0:ch){}
无符号字符_val=0;
};
模板
课堂示范:私人基地
{
公众:
演示()=默认值;
//普通复制、移动构造函数/赋值和普通析构函数
constexpr演示(演示const&)=默认值;
constexpr演示(演示&)=默认值;
演示和运算符=(演示常量&)=默认值;
演示和运算符=(演示和运算符)=默认值;
~display()=默认值;
显式constexpr演示(无符号字符转换)
:基本(转换)
{
}
char myValue()常量{
返回基数::\u val;
}
};
#包括
使用名称空间std;
int main()
{
即使编译了它,演示
在技术上仍然不是POD。“普通类是一个具有默认构造函数、没有非普通默认构造函数且可复制的类。”演示
有两个默认构造函数,其中一个是非平凡的,即使它永远不可能是重载解析的可行函数。CRTP实现重复函数,并使这些构造函数具有两个专门化?您不能使用模板默认构造函数,因为您不能显式指定其模板参数。您可以只创建带有参数的模板构造函数,这些参数将允许编译器推断其模板参数。您可以尝试使用模板静态函数实现所需的功能,该函数返回演示
类的构造对象。谢谢大家,这消除了我的困惑。@Yakk:CRTP看起来是实现基于模板参数的类可以是POD或非POD,没有大量重复;如果您将其作为答案提交,我将接受它。@表示没有什么不好的,只是自我回答:我现在不想写一个好的答案。一个坏的答案不值得写。
is_pod<base<true>>::value = 1
is_pod<base<false>>::value = 0
is_pod<Demonstration<true>>::value = 1
is_pod<Demonstration<false>>::value = 0
(int)Demonstration<true>(1).myValue() = 1
(int)Demonstration<false>(101).myValue() = 0