将整数(文字)与函数相关联,让呼叫者查询拖鞋的数量



i在具有BLAS功能,模板操作员和迭代求解器的高性能代码上工作。为了进行性能测量,我们使用手动计算的"有用"拖放数量,然后除以算法所需的时间。这可以使用"有用"的性能。

模板是类,因此我可以添加virtual int get_flops() const成员功能。在迭代求解器中,我只会从各种模板呼叫中加起来拖鞋。

但是,BLAS例程是函数。它们就像void copyVector(V a, const V b)。我想将整数0与此功能相关联。使用返回值似乎是一个快速修复,但我可能想稍后再添加另一个注释。

一种选择是将这些选择转变为使用operator()的Singleton课程,但这感觉就像违反了开放式原理(OCP(。是否有类型的特质我可以为函数做的?

我可能会做更多类似的事情:

#include <type_traits>
#include <iostream>
struct dummy { };
template <class T>
struct flop_map {
    static int value;
};
template <class T>
int flop_map<T>::value;
#define FOO_ID(foo) std::integral_constant<decltype(&foo), &foo>
void blas_routine(double *const, double const *const) {}
void other(int, int) {}
int main() {
    flop_map<FOO_ID(blas_routine)>::value = 0;
    flop_map<FOO_ID(other)>::value        = 4;
    std::cout << flop_map<FOO_ID(blas_routine)>::value << std::endl;
    std::cout << flop_map<FOO_ID(other)>::value << std::endl;
}

[live demo]

您可以创建Global unordered_map,并使用功能指针进行关联整数。这样的东西:

std::unordered_map<void(*)(void), int> tmp;

据我所记得的标准保证,所有类型的功能指针具有相同的大小,并且由于您只使用功能指针将索引索引到映射中,因此您可以将任何功能指针(而不是指针to to member tho(void void(**((void(并从unordered_map中设置/检索。

基于RadosławCybulski的答案,我将其扩展到完整的工作版本:

#include <iostream>
#include <unordered_map>
template <typename Annotation>
class FunctionAnnotation {
  public:
    template <typename R, typename... Args>
    Annotation get(R (*func)(Args...)) {
        return map_.at(strip(func));
    }
    template <typename R, typename... Args>
    void set(R (*func)(Args...), Annotation annotation) {
        map_[strip(func)] = annotation;
    }
  private:
    // Basic function pointer type.
    typedef void (*VoidFunc)();
    // Type stripping function that will take a function pointer and return a
    // function with the wrong but unified type.
    template <typename R, typename... Args>
    VoidFunc strip(R (*func)(Args...)) {
        return reinterpret_cast<VoidFunc>(func);
    }
    // The map with annotation values.
    std::unordered_map<VoidFunc, Annotation> map_;
};
FunctionAnnotation<int> flop_map;
// Some example functions.
void blas_routine(double *const dest, double const *const src) {}
void other(int a, int b) {}
int main() {
    // Populate that map.
    flop_map.set(blas_routine, 0);
    flop_map.set(other, 4);
    // Later on use that.
    std::cout << flop_map.get(blas_routine) << std::endl;
    std::cout << flop_map.get(other) << std::endl;
}

这在C 11和C 14模式中用GCC干净地编译。输出是预期的:

0
4

最新更新