3

所以我有以下测试代码:

struct empty_value{
    template<typename T>
    T as(){ return T(0); }
};

template<typename T, typename U, typename F>
auto empty_func(empty_value lhs, empty_value rhs, F f) -> decltype(f(lhs.as<T>(), rhs.as<U>())){
    return f(lhs.as<T>(), rhs.as<U>());
}

template<typename T, typename U, template<typename, typename> class F>
static auto bind_empty_f = std::bind(empty_func<T, U, F<T, U>>, std::placeholders::_1, std::placeholders::_2, F<T, U>{});

template<typename F>
void other_test_func(F&&){}

template<typename T, typename U, template<typename, typename> class F>
void test_func(){
    other_test_func(bind_empty_f<T, U, F>);
}

template<typename T, typename U>
struct my_add{
    decltype(auto) operator()(T lhs, U rhs){ return lhs + rhs; }
};

int main(){
    test_func<float, int, my_add>();
}

这源于我实际正在研究的东西。问题出现在bind_empty_f. 但只有当它被传递给other_test_func. 当我尝试将它分配给这样的常规变量时:

int main(){
    auto var = bind_empty_f<float, int, my_add>;
}

一切都很愉快。但是,如果我调用test_funcwhich 尝试将其传递给other_test_func我,则会收到一个错误,即返回的基础类型std::bind无法转换为float. 所以它试图将其转换为实际函数的返回值。我不明白为什么。我在哪里传递函数的返回值?


编辑

如果我在将局部变量设置为bind_empty_ffirst 的值后调用该函数,它将编译:

int main(){
    auto var = bind_empty_f<float, int, my_add>;
    test_func<float, int, my_add>;
}

所以问题必须与静态初始化一个编译器错误有关。

编辑2

如评论中所述,这个确切的示例可以使用其他编译器编译,但不能使用原始测试编译器(GCC 5.2.0)。

这是 GCC 5.2 或所有其他经过测试的编译器中的错误。

所以我想问题变成了,这个标准符合代码吗?

4

1 回答 1

3

这是您的问题的一个最小示例:

template<class T> struct tag {};

template<typename T>
static auto bind_empty_f = tag<T>{};

template<typename T>
decltype(bind_empty_f<T>) test_func(){
  return 3.14f;
}

然后我们简单地test_func<float>()返回3.14f。如果我们test_func<int>()返回3.

如果我们先执行 a bind_empty_f<float>test_func<float>则会产生错误。

bind_empty_f<T>在另一个模板中调用它时推导出的类型设置为T而不是表达式右侧的类型。

如果您直接调用它,并且尚未计算类型(似乎有缓存),则推断出正确的类型,并且我test_func的构建失败(因为它试图转换3.14fbind表达式类型并失败)。

这绝对是编译器的问题。您可以通过将autoin替换bind_empty_fstd::decay_t<decltype(stuff_on_rhs)>.

请注意,您的某些绑定表达式还有其他问题,但它们不是此问题的核心。

现场示例编译(错误)现场示例未编译(正确)

于 2015-09-09T18:30:29.377 回答