9

我有一个函数可以扫描用户的文件系统,用路径填充一个向量,然后对它进行排序或不排序。由于用户应该能够在编译时决定是否要对向量进行排序,因此我使用模板和辅助类来代替非常需要的(但不存在的)“静态 if”。

考虑这段代码:

enum class Sort{Alphabetic, Unsorted};  

template<Sort TS> struct SortHelper;
template<> struct SortHelper<Sort::Alphabetic>
{
    static void sort(vector<string>& mTarget) { sort(begin(mTarget), end(mTarget)); }
};
template<> struct SortHelper<Sort::Unsorted>
{
    static void sort(vector<string>&) { }
};

template<Sort TS> struct DoSomethingHelper
{
    static void(vector<string>& mTarget)
    {
         // do something with mTarget
         SortHelper<TS>::sort(mTarget);
    }   
};

我在上面编写的代码与原始代码相比得到了极大的简化,它采用多个模板参数,以允许用户在编译时进一步自定义函数的结果。

有没有使用所有这些帮助类的替代方法?它变得非常混乱且难以阅读。

理想情况下,这就是我想写的:

enum class Sort{Alphabetic, Unsorted};  
template<Sort TS> struct DoSomethingHelper
{
    static void(vector<string>& mTarget)
    {
         // do something with mTarget
         static_if(TS == Sort::Unsorted) { /* do nothing */ }
         static_if(TS == Sort::Alphabetic) { sort(begin(mTarget), end(mTarget)); }
    }   
};
4

3 回答 3

18

由于您的值在编译时已知(非模板类型参数),您可以完美地编写“正常” if

template<Sort TS>
void someFunction(vector<string>& mTarget)
{
     if (TS == Sort::Alphabetic) { sort(begin(mTarget), end(mTarget)); }
     // else if (TS == Sort::Unsorted) {}
}

编译器将执行常量折叠死代码消除(当然,如果启用了这些优化),结果将与您使用假设的static_if.

于 2013-06-10T13:20:50.933 回答
12

恐怕对static_if.

当然,您可以使用static_if(或您真正希望的任何技巧)尝试进行一些优化,但这不是它的首要目标。

的第一个目标static_if语义的。让我用std::advance. 的典型实现std::advance将使用类型开关在编译时在 O(1) 实现(对于随机访问迭代器)和 O(n) 实现(对于其他实现)之间进行选择:

template <typename It, typename D>
void advance_impl(It& it, D d, random_access_iterator_tag)
{
    it += d;
}

template <typename It, typename D>
void advance_impl(It& it, D d, bidirectional_iterator_tag)
{
    if (d > D(0)) { for (D i(0); i < d; ++i) { ++it; } }
    else          { for (D i(0); i > d; --i) { --it; } }
}

template <typename It, typename D>
void advance_impl(It& it, D d, input_iterator_tag)
{
    for (D i(0); i < d; ++i) { ++it; }
}

最后:

template <typename It, typename D>
void advance(It& it, D d)
{
    typename std::iterator_traits<It>::iterator_category c;
    advance_impl(it, d, c);
}

为什么不在if这种情况下只使用 a ?因为它不会编译。

  • 双向迭代器不支持+=
  • 输入迭代器(或前向迭代器)不支持--

因此,实现该功能的唯一方法是仅使用给定类型上的可用操作静态分派给函数。

于 2013-06-10T14:27:54.177 回答
0

模板专业化呢?

#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

enum class Sort {
    Alphabetic, 
    Unsorted
};

template<Sort TS> struct DoSomethingHelper {
    static void someFunction(vector<string>& mTarget)
    {}  
};

template<> struct DoSomethingHelper<Sort::Unsorted> {
    static void someFunction(vector<string>& mTarget) {

    }  
};

template<> struct DoSomethingHelper<Sort::Alphabetic> {
    static void someFunction(vector<string>& mTarget) {
        sort(begin(mTarget), end(mTarget));
    }  
};

int main() {
    vector<string> v = {{"foo", "bar", "foo2", "superman", ".."}};

    DoSomethingHelper<Sort::Alphabetic> helper;
    helper.someFunction(v);

    for (string& s : v) {
        cout << s << endl;
    }
    return 0;
}

编辑:我是个白痴。

于 2013-06-10T20:03:35.107 回答