Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否可以使用模板元编程对类将执行的功能进行编译时选择?_C++_Templates - Fatal编程技术网

C++ 是否可以使用模板元编程对类将执行的功能进行编译时选择?

C++ 是否可以使用模板元编程对类将执行的功能进行编译时选择?,c++,templates,C++,Templates,我经常这样写课程: Logger::Logger(bool log_time_, bool log_percentage, bool log_size):log_time(log_time_)... //made up example Logger::Log() { string log_line; if (log_time) log_line+=(get_time()); if (log_perc

我经常这样写课程:

    Logger::Logger(bool log_time_, bool log_percentage, bool log_size):log_time(log_time_)... //made up example

    Logger::Log()
    {
        string log_line;
        if (log_time)
            log_line+=(get_time());
        if (log_percentage)
            log_line+=(get_percentage());
        //...
    }
template <bool Opt1, bool Opt2> void foo()
{
     Action1<Opt1>();
     Action2<Opt2>();
}

template <bool> void Action1();
template <bool> void Action2();

template <> void Action1<true>()  { /* ... */ }
template <> void Action1<false>() { /* ... */ }
template <> void Action2<true>()  { /* ... */ }
template <> void Action2<false>() { /* ... */ }
我想知道有没有办法将使用模板魔术的类转换成在编译时执行“if(something)”部分的代码

编辑:
bool变量的值在编译时是已知的。

是的,这是可能的,尽管有些编译器不喜欢它。但是,您最终将得到一组不同的类,因为您必须提供布尔值作为模板说明符(可能不是正确的术语)


我想你最好还是用虚拟日志的方法来代替?然后创建几个类,每个类定义自己的日志方法。除非您有其他原因,否则我建议在这种情况下使用虚拟函数而不是模板。

是的,这是可能的,尽管有些编译器不喜欢您使用虚拟函数。但是,您最终将得到一组不同的类,因为您必须提供布尔值作为模板说明符(可能不是正确的术语)


我想你最好还是用虚拟日志的方法来代替?然后创建几个类,每个类定义自己的日志方法。除非您有其他原因,否则我建议在这种情况下使用虚拟函数而不是模板。

当然。大概是这样的:

    Logger::Logger(bool log_time_, bool log_percentage, bool log_size):log_time(log_time_)... //made up example

    Logger::Log()
    {
        string log_line;
        if (log_time)
            log_line+=(get_time());
        if (log_percentage)
            log_line+=(get_percentage());
        //...
    }
template <bool Opt1, bool Opt2> void foo()
{
     Action1<Opt1>();
     Action2<Opt2>();
}

template <bool> void Action1();
template <bool> void Action2();

template <> void Action1<true>()  { /* ... */ }
template <> void Action1<false>() { /* ... */ }
template <> void Action2<true>()  { /* ... */ }
template <> void Action2<false>() { /* ... */ }
模板void foo()
{
行动1();
行动2();
}
模板void Action1();
模板void Action2();
模板void Action1(){/*…*/}
模板void Action1(){/*…*/}
模板void Action2(){/*…*/}
模板void Action2(){/*…*/}

像调用
foo()一样调用这个函数

当然可以。大概是这样的:

    Logger::Logger(bool log_time_, bool log_percentage, bool log_size):log_time(log_time_)... //made up example

    Logger::Log()
    {
        string log_line;
        if (log_time)
            log_line+=(get_time());
        if (log_percentage)
            log_line+=(get_percentage());
        //...
    }
template <bool Opt1, bool Opt2> void foo()
{
     Action1<Opt1>();
     Action2<Opt2>();
}

template <bool> void Action1();
template <bool> void Action2();

template <> void Action1<true>()  { /* ... */ }
template <> void Action1<false>() { /* ... */ }
template <> void Action2<true>()  { /* ... */ }
template <> void Action2<false>() { /* ... */ }
模板void foo()
{
行动1();
行动2();
}
模板void Action1();
模板void Action2();
模板void Action1(){/*…*/}
模板void Action1(){/*…*/}
模板void Action2(){/*…*/}
模板void Action2(){/*…*/}

像调用
foo()一样调用这个函数

对于编译时常量,您可以使用
模板
编程:

template<bool log_time, bool log_perchentage, bool log_size>
struct Logger
{
  static void log()
  {  // log everything
    string log_line;
    log_line+=(get_time());
    log_line+=(get_perchentage());
    log_line+=(get_size());
  }
};

template<>
struct Logger<false, false, false>
{
  static void log()
  {  // nothing to log
  }
};
模板
结构记录器
{
静态无效日志()
{//记录一切
字符串日志行;
log_line+=(get_time());
log_line+=(get_percentage());
log_line+=(get_size());
}
};
样板
结构记录器
{
静态无效日志()
{//没有要记录的内容
}
};

您还可以将中间版本专门化为
Logger
Logger
等。另一种避免几种专门化的方法是将
时间/百分比/大小
分为不同的
结构
并分别记录它们。

对于编译时常量,您可以使用
模板
编程:

template<bool log_time, bool log_perchentage, bool log_size>
struct Logger
{
  static void log()
  {  // log everything
    string log_line;
    log_line+=(get_time());
    log_line+=(get_perchentage());
    log_line+=(get_size());
  }
};

template<>
struct Logger<false, false, false>
{
  static void log()
  {  // nothing to log
  }
};
模板
结构记录器
{
静态无效日志()
{//记录一切
字符串日志行;
log_line+=(get_time());
log_line+=(get_percentage());
log_line+=(get_size());
}
};
样板
结构记录器
{
静态无效日志()
{//没有要记录的内容
}
};

您还可以将中间版本专门化为
Logger
Logger
等。另一种避免多个专门化的方法是将
time/percentage/size
分为不同的
struct
并分别记录它们。

您可以这样做

struct DummyEnhancer 
{
    void operator()(string& s) const{
    }
};

struct TimerEnhancer
{
    void operator()(string& s) const{
        s += "time";
    }
};

struct PercenterEnhancer
{
    void operator()(string& s) const{
        s += "percent";
    }
};

template <typename Timer , typename Percenter>
struct Logger
{
    void Log()
    {
        string log_line;

        Timer t;
        t( log_line );

        Percenter p;
        p( log_line );
    }
};

int main()
{

    Logger<DummyEnhancer,DummyEnhancer> foo;
    foo.Log();

    Logger< TimerEnhancer , PercenterEnhancer > bar;
    bar.Log();

    return 0;
}
struct dummeyenhancer
{
void运算符()(字符串和s)常量{
}
};
结构TimerEnhancer
{
void运算符()(字符串和s)常量{
s+=“时间”;
}
};
结构百分比增强器
{
void运算符()(字符串和s)常量{
s+=“百分比”;
}
};
样板
结构记录器
{
无效日志()
{
字符串日志行;
定时器t;
t(对数线);
百分比p;
p(对数线);
}
};
int main()
{
傅先生;
foo.Log();
记录器bar;
bar.Log();
返回0;
}

foo.Log()

struct DummyEnhancer 
{
    void operator()(string& s) const{
    }
};

struct TimerEnhancer
{
    void operator()(string& s) const{
        s += "time";
    }
};

struct PercenterEnhancer
{
    void operator()(string& s) const{
        s += "percent";
    }
};

template <typename Timer , typename Percenter>
struct Logger
{
    void Log()
    {
        string log_line;

        Timer t;
        t( log_line );

        Percenter p;
        p( log_line );
    }
};

int main()
{

    Logger<DummyEnhancer,DummyEnhancer> foo;
    foo.Log();

    Logger< TimerEnhancer , PercenterEnhancer > bar;
    bar.Log();

    return 0;
}
struct dummeyenhancer
{
void运算符()(字符串和s)常量{
}
};
结构TimerEnhancer
{
void运算符()(字符串和s)常量{
s+=“时间”;
}
};
结构百分比增强器
{
void运算符()(字符串和s)常量{
s+=“百分比”;
}
};
样板
结构记录器
{
无效日志()
{
字符串日志行;
定时器t;
t(对数线);
百分比p;
p(对数线);
}
};
int main()
{
傅先生;
foo.Log();
记录器bar;
bar.Log();
返回0;
}
foo.Log()
本文将提供两种解决方案,一种使用C++03,另一种使用C++11

如果你想要一个真正的编译时间(如果保证的话)没有任何运行时开销(没有函数跳转等),那就很难(即,你需要编写很多代码)

然而,这是可能的,尽管如果您想在代码中添加另一个选项(在C++03中),那么代码的维护将非常繁琐。我建议您查看以下解决方案


C++03中的解决方案 您的编译器应该足够聪明,可以优化掉对
LogHelper
的任何调用,不过如果您只是寻找可读性更强的代码,而不是获得优异的性能,那么这种语法是非常好的

enum LoggerType {
  NONE    =0,
  DATE    = (1<<0),
  TIME    = (1<<1),
  PERCENT = (1<<2)
};

template<int>     void LogHelper (std::string&);

template<> inline void LogHelper<+NONE>    (std::string&)   {}
template<> inline void LogHelper<+DATE>    (std::string& s) {s += "1970-01-01 ";}
template<> inline void LogHelper<+TIME>    (std::string& s) {s += "12:01:01 ";}
template<> inline void LogHelper<+PERCENT> (std::string& s) {s += "42% ";}

template<int LOG_FLAG = NONE>
struct Logger {
  static void log (std::string const& description) {
    std::string s1;

    LogHelper<DATE    & LOG_FLAG> (s1);
    LogHelper<TIME    & LOG_FLAG> (s1);
    LogHelper<PERCENT & LOG_FLAG> (s1);

    std::cerr.width (25);
    std::cerr << s1 << " >> " << description << std::endl;
  }
};

使用可变模板的解决方案(C++11) 前言 本文将提供两种解决方案,一种使用C++03,另一种使用C++11

如果你想要一个真正的编译时间(如果保证的话)没有任何运行时开销(没有函数跳转等),那就很难(即,你需要编写很多代码)

然而,这是可能的,尽管如果您愿意,代码的维护将非常繁琐