模板模板条件编译
Template template conditional compilation
我不知道我使用的策略是否正确,但我想使用带有 bool 值参数的模板,这样当 method1 和 method2 设置为 false 时,我不必调用 fmethod1 或fmethod2.我可以使用动态表来做到这一点,但我刚刚发现我可以使用模板来做到这一点,并且我正在训练这种语法用法,如下所示:
#include<iostream>
template<bool method1, bool method2>
class Caller {
public:
Caller(const float prop1, const float prop2):prop1(prop1),prop2(prop2){;}
float prop1;
float prop2;
bool fmethod1(){
return prop1;
}
bool fmethod2(){
return prop2;
}
void mainMethod(){
std::cout << "Caller<" << method1 << "," << method2 << ">(" << prop1 << ")" << std::endl;
std::cout << "fmethod1()" << fmethod1() << std::endl;
std::cout << "fmethod2()" << fmethod2() << std::endl;
};
};
template<>
class Caller<true,false> {
public:
Caller(const float prop2):prop2(prop2){;}
float prop2;
// I can declare here to return true, but this
// shouldn't be called in Wrapper, since Wrapper method1 is set
// to false (the first "or" on wrapper should be set to true and
// compiler shouldn't need this method.)
bool fmethod1();
bool fmethod2(){
return prop2;
}
void mainMethod(){
std::cout << "Caller<true,false>" << std::endl;
std::cout << "fmethod2()" << fmethod2() << std::endl;
};
};
template<>
class Caller<false,true> {
public:
Caller(const float prop1):prop1(prop1){;}
float prop1;
bool fmethod1(){
return prop1;
}
bool fmethod2(); // Same here
void mainMethod(){
std::cout << "Caller<false,true>" << std::endl;
std::cout << "fmethod1()" << fmethod1() << std::endl;
};
};
template<>
class Caller<false,false> {
public:
bool fmethod1(){
return true;
}
bool fmethod2(){
return true;
}
void mainMethod(){
std::cout << "Caller<false,false>" << std::endl;
std::cout << "fmethod1()" << fmethod1() << std::endl;
std::cout << "fmethod2()" << fmethod2() << std::endl;
};
};
template<template<bool, bool> class holded_t,bool method1, bool method2>
class Wrapper{
public:
holded_t<method1,method2> holded;
Wrapper():holded(holded_t<method1,method2>()){;}
Wrapper(float prop1):holded(holded_t<method1,method2>(prop1)){;}
Wrapper(float prop1, float prop2):holded(holded_t<method1,method2>(prop1,prop2)){;}
void mainMethod(){
if( !method1 || holded.fmethod1() ){
if( !method2 || holded.fmethod2() ){
holded.mainMethod();
} else {
std::cout << "holded method2 is false" << std::endl;
}
} else {
std::cout << "holded method1 is false" << std::endl;
}
}
};
int main(){
Wrapper<Caller,false,false> holder_ex_false_false;
holder_ex_false_false.mainMethod();
Wrapper<Caller,false,true> holder_ex_false_true(0);
holder_ex_false_true.mainMethod();
Wrapper<Caller,true,false> holder_ex_true_false(0);
holder_ex_true_false.mainMethod();
Wrapper<Caller,true,true> holder_ex_true_true(0,0);
holder_ex_true_true.mainMethod();
Wrapper<Caller,true,true> holder_ex_true_true1(1,0);
holder_ex_true_true1.mainMethod();
Wrapper<Caller,true,true> holder_ex_true_true2(0,1);
holder_ex_true_true2.mainMethod();
Wrapper<Caller,true,true> holder_ex_true_true3(1,1);
holder_ex_true_true3.mainMethod();
}
我可以在专业化中声明 fmethod1
和 fmethod2
方法(将其设置为 return true),以便它给出以下结果:
Caller<false,false>
fmethod1()1
fmethod2()1
Caller<false,true>
fmethod1()0
fmethod2()1
Caller<true,false>
fmethod1()1
fmethod2()0
holded method1 is false
holded method2 is false
holded method1 is false
Caller<1,1>(1)
fmethod1()1
fmethod2()1
但我想要一种方法来做到这一点,这样我就不需要为 Caller
实现 method1 或 method2,如果 Wrapper
不需要的话,但似乎当模板 属性 method1 为 false 时,编译器 (gcc
) 看不到我永远不需要 fmethod1。
我的第一个问题是,如果我从这种方法中获得任何好处,而不是从正常的继承 virtual
方法中获得任何好处,这类似于:
class Caller{
public:
virtual bool fmethod1(){return true;}
virtual bool fmethod2(){return true;}
}
class CallerMethod1Active: public Caller{
public:
float prop1;
bool fmethod1(){return prop1;}
bool fmethod2(){return true;}
}
…
其次,关于如何在不需要实施的情况下实施这个想法的任何想法 Caller fmethod1
?
您可能会考虑奇怪的重复模板模式并使用静态多态性:
#include <iostream>
template<typename Derived>
class BasicCaller
{
protected:
BasicCaller() {}
public:
void method() {
static_cast<Derived*>(this)->method1();
static_cast<Derived*>(this)->method2();
}
protected:
bool method1() { return false; }
bool method2() { return false; }
};
class CallNone : public BasicCaller<CallNone> {};
class CallFirst : public BasicCaller<CallFirst>
{
friend class BasicCaller<CallFirst>;
protected:
bool method1() {
std::cout << "First\n";
return true;
}
};
class CallSecond : public BasicCaller<CallSecond>
{
friend class BasicCaller<CallSecond>;
protected:
bool method2() {
std::cout << "Second\n";
return true;
}
};
class CallBoth : public BasicCaller<CallBoth>
{
friend class BasicCaller<CallBoth>;
protected:
bool method1() {
std::cout << "Both First\n";
return true;
}
bool method2() {
std::cout << "Both Second\n";
return true;
}
};
int main()
{
std::cout << "CallNone\n";
CallNone a;
a.method();
std::cout << "CallFirst\n";
CallFirst b;
b.method();
std::cout << "CallSecond\n";
CallSecond c;
c.method();
std::cout << "CallBoth\n";
CallBoth d;
d.method();
}
在您的 Wrapper
中,您可以将对 fmethod1
和 fmethod2
的调用移动到单独的辅助函数中,只有在存在正确的模板参数时才会实例化这些函数:
void mainMethod(){
if( testmethod1(std::integral_constant<bool, method1>()) ){
if( testmethod2(std::integral_constant<bool, method2>()) ){
holded.mainMethod();
} else {
std::cout << "holded method2 is false" << std::endl;
}
} else {
std::cout << "holded method1 is false" << std::endl;
}
}
bool testmethod1(std::true_type) { return holded.fmethod1(); }
bool testmethod1(std::false_type) { return false; }
bool testmethod2(std::true_type) { return holded.fmethod2(); }
bool testmethod2(std::false_type) { return false; }
因为这是一个class模板,成员函数只有在被调用时才被实例化,重载解析不会尝试调用与参数不匹配的函数。
您的函数缺少 const
限定符,但这与问题无关。
我不知道我使用的策略是否正确,但我想使用带有 bool 值参数的模板,这样当 method1 和 method2 设置为 false 时,我不必调用 fmethod1 或fmethod2.我可以使用动态表来做到这一点,但我刚刚发现我可以使用模板来做到这一点,并且我正在训练这种语法用法,如下所示:
#include<iostream>
template<bool method1, bool method2>
class Caller {
public:
Caller(const float prop1, const float prop2):prop1(prop1),prop2(prop2){;}
float prop1;
float prop2;
bool fmethod1(){
return prop1;
}
bool fmethod2(){
return prop2;
}
void mainMethod(){
std::cout << "Caller<" << method1 << "," << method2 << ">(" << prop1 << ")" << std::endl;
std::cout << "fmethod1()" << fmethod1() << std::endl;
std::cout << "fmethod2()" << fmethod2() << std::endl;
};
};
template<>
class Caller<true,false> {
public:
Caller(const float prop2):prop2(prop2){;}
float prop2;
// I can declare here to return true, but this
// shouldn't be called in Wrapper, since Wrapper method1 is set
// to false (the first "or" on wrapper should be set to true and
// compiler shouldn't need this method.)
bool fmethod1();
bool fmethod2(){
return prop2;
}
void mainMethod(){
std::cout << "Caller<true,false>" << std::endl;
std::cout << "fmethod2()" << fmethod2() << std::endl;
};
};
template<>
class Caller<false,true> {
public:
Caller(const float prop1):prop1(prop1){;}
float prop1;
bool fmethod1(){
return prop1;
}
bool fmethod2(); // Same here
void mainMethod(){
std::cout << "Caller<false,true>" << std::endl;
std::cout << "fmethod1()" << fmethod1() << std::endl;
};
};
template<>
class Caller<false,false> {
public:
bool fmethod1(){
return true;
}
bool fmethod2(){
return true;
}
void mainMethod(){
std::cout << "Caller<false,false>" << std::endl;
std::cout << "fmethod1()" << fmethod1() << std::endl;
std::cout << "fmethod2()" << fmethod2() << std::endl;
};
};
template<template<bool, bool> class holded_t,bool method1, bool method2>
class Wrapper{
public:
holded_t<method1,method2> holded;
Wrapper():holded(holded_t<method1,method2>()){;}
Wrapper(float prop1):holded(holded_t<method1,method2>(prop1)){;}
Wrapper(float prop1, float prop2):holded(holded_t<method1,method2>(prop1,prop2)){;}
void mainMethod(){
if( !method1 || holded.fmethod1() ){
if( !method2 || holded.fmethod2() ){
holded.mainMethod();
} else {
std::cout << "holded method2 is false" << std::endl;
}
} else {
std::cout << "holded method1 is false" << std::endl;
}
}
};
int main(){
Wrapper<Caller,false,false> holder_ex_false_false;
holder_ex_false_false.mainMethod();
Wrapper<Caller,false,true> holder_ex_false_true(0);
holder_ex_false_true.mainMethod();
Wrapper<Caller,true,false> holder_ex_true_false(0);
holder_ex_true_false.mainMethod();
Wrapper<Caller,true,true> holder_ex_true_true(0,0);
holder_ex_true_true.mainMethod();
Wrapper<Caller,true,true> holder_ex_true_true1(1,0);
holder_ex_true_true1.mainMethod();
Wrapper<Caller,true,true> holder_ex_true_true2(0,1);
holder_ex_true_true2.mainMethod();
Wrapper<Caller,true,true> holder_ex_true_true3(1,1);
holder_ex_true_true3.mainMethod();
}
我可以在专业化中声明 fmethod1
和 fmethod2
方法(将其设置为 return true),以便它给出以下结果:
Caller<false,false>
fmethod1()1
fmethod2()1
Caller<false,true>
fmethod1()0
fmethod2()1
Caller<true,false>
fmethod1()1
fmethod2()0
holded method1 is false
holded method2 is false
holded method1 is false
Caller<1,1>(1)
fmethod1()1
fmethod2()1
但我想要一种方法来做到这一点,这样我就不需要为 Caller
实现 method1 或 method2,如果 Wrapper
不需要的话,但似乎当模板 属性 method1 为 false 时,编译器 (gcc
) 看不到我永远不需要 fmethod1。
我的第一个问题是,如果我从这种方法中获得任何好处,而不是从正常的继承 virtual
方法中获得任何好处,这类似于:
class Caller{
public:
virtual bool fmethod1(){return true;}
virtual bool fmethod2(){return true;}
}
class CallerMethod1Active: public Caller{
public:
float prop1;
bool fmethod1(){return prop1;}
bool fmethod2(){return true;}
}
…
其次,关于如何在不需要实施的情况下实施这个想法的任何想法 Caller fmethod1
?
您可能会考虑奇怪的重复模板模式并使用静态多态性:
#include <iostream>
template<typename Derived>
class BasicCaller
{
protected:
BasicCaller() {}
public:
void method() {
static_cast<Derived*>(this)->method1();
static_cast<Derived*>(this)->method2();
}
protected:
bool method1() { return false; }
bool method2() { return false; }
};
class CallNone : public BasicCaller<CallNone> {};
class CallFirst : public BasicCaller<CallFirst>
{
friend class BasicCaller<CallFirst>;
protected:
bool method1() {
std::cout << "First\n";
return true;
}
};
class CallSecond : public BasicCaller<CallSecond>
{
friend class BasicCaller<CallSecond>;
protected:
bool method2() {
std::cout << "Second\n";
return true;
}
};
class CallBoth : public BasicCaller<CallBoth>
{
friend class BasicCaller<CallBoth>;
protected:
bool method1() {
std::cout << "Both First\n";
return true;
}
bool method2() {
std::cout << "Both Second\n";
return true;
}
};
int main()
{
std::cout << "CallNone\n";
CallNone a;
a.method();
std::cout << "CallFirst\n";
CallFirst b;
b.method();
std::cout << "CallSecond\n";
CallSecond c;
c.method();
std::cout << "CallBoth\n";
CallBoth d;
d.method();
}
在您的 Wrapper
中,您可以将对 fmethod1
和 fmethod2
的调用移动到单独的辅助函数中,只有在存在正确的模板参数时才会实例化这些函数:
void mainMethod(){
if( testmethod1(std::integral_constant<bool, method1>()) ){
if( testmethod2(std::integral_constant<bool, method2>()) ){
holded.mainMethod();
} else {
std::cout << "holded method2 is false" << std::endl;
}
} else {
std::cout << "holded method1 is false" << std::endl;
}
}
bool testmethod1(std::true_type) { return holded.fmethod1(); }
bool testmethod1(std::false_type) { return false; }
bool testmethod2(std::true_type) { return holded.fmethod2(); }
bool testmethod2(std::false_type) { return false; }
因为这是一个class模板,成员函数只有在被调用时才被实例化,重载解析不会尝试调用与参数不匹配的函数。
您的函数缺少 const
限定符,但这与问题无关。