【问题标题】:Check function template validity in C++14 when using -Waddress使用 -Waddress 时检查 C++14 中的函数模板有效性
【发布时间】:2019-03-17 22:26:39
【问题描述】:

使用-Waddress编译此代码时:

#include <iostream>
#include <memory>
#include <string.h>

template <typename T, void (*func)(T*) = nullptr>
struct Caller {
    Caller(T* ptr = nullptr)
    {
        std::cout
            << "Creating caller " << ptr
            << ", is function " << std::is_function<decltype(func)>()
            << ", is null " << std::is_null_pointer<decltype(func)>()
            << ", function is " << func
            << std::endl;

        if (func)
        {
            std::cout << "Running for " << ptr << " func " << func << std::endl;
            func(ptr);
        }
    }
};

void free_char(char *c) { free(c); }

int main() {
    Caller<char, free_char>(strdup("Test"));
    Caller<const char>("Test2");
    return 0;
}

它会失败:

/tmp/foo.cpp: In instantiation of ‘Caller<T, func>::Caller(T*) [with T = char; void (* func)(T*) = free_char]’:
/tmp/foo.cpp:36:40:   required from here
/tmp/foo.cpp:13:33: warning: the address of ‘void free_char(char*)’ will never be NULL [-Waddress]

一种解决方法是使用 if (auto f = func) f(ptr); 之类的东西,但我希望在编译时进行静态检查。

This solution 提到了模板专业化的使用,但这里我们正在处理结构的一部分,这是我想使用静态模板检查的情况。

【问题讨论】:

  • 对不起,你为什么不能使用模板专业化?
  • 为什么不在构造函数中取一个函数指针呢? coliru.stacked-crooked.com/a/60f81dec07918597
  • if constexpr 在 C++17 中。
  • @Jarod42 是的,我知道这一点,但如前所述,我们还没有准备好 :)
  • @NathanOliver 因为它需要是一个类型,我只是通过传递一个新模板来生成新的。

标签: c++ c++11 templates c++14


【解决方案1】:

默认情况下简单地提供一个无操作函数而不是空指针怎么样?这完全摆脱了if,使代码更干净。

template<typename T>
void no_op(T*) {}

template <typename T, void (*func)(T*) = no_op<T>>
struct Caller {
    static_assert(func != nullptr, "don't pass nullptr");
    Caller(T* ptr = nullptr)
    {
        std::cout
            << "Creating caller " << ptr
            << ", is function " << std::is_function<decltype(func)>()
            << ", is null " << std::is_null_pointer<decltype(func)>()
            << ", function is " << func
            << std::endl;

        std::cout << "Running for " << ptr << " func " << func << std::endl;
        func(ptr);
    }
};

【讨论】:

  • 事实是,在我的情况下,我不仅不想在无效时不调用函数,而且还改变行为....在这种情况下,我想检查 no_op 函数仍然会生成同样的(总是正确的)事情......
猜你喜欢
  • 2017-07-29
  • 1970-01-01
  • 2017-05-08
  • 1970-01-01
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 2015-07-20
  • 2020-05-16
相关资源
最近更新 更多