我想通过模板参数在编译时切换默认构造函数的定义。我可以让它为转换构造函数编译OK,但尝试使用该方法默认构造函数是否默认 - 如果在特定模板参数的情况下,生成的类可能是POD,但在另一种情况下,它不能 - 但这样做时我得到编译器错误。如果没有专门化模板并复制所有相同的代码,有没有办法做到这一点?这是我正在尝试的简化版本:
#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;
};
答案 0 :(得分:0)
GCC抱怨你的模板:
error: a template cannot be defaulted
和Clang抱怨道:
error: only special member functions may be defaulted.
这看起来很公平。成员函数模板不是成员函数, 更别说一个特别的了。
当Demonstration<bool P>
为真时,您希望P
成为POD
不一定如此。
一种可能的解决方案是完全委托POD-ness的参数化
到基础模板base<bool P>
的特化和拥有
Demonstration<P>
继承base<P>
。这是一个例子:
#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;
}
现在Demonstration<P>
是POD,以防base<P>
是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
使用GCC 4.8.2和clang 3.3构建