使用模板变量

时间:2015-09-09 17:07:45

标签: c++ templates gcc c++14 gcc5.2

所以我有以下测试代码:

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_func试图将其传递给other_test_func,我会收到错误,std::bind返回的基础类型无法转换为float。所以它试图将它转换为实际函数的返回值。我不明白为什么。我在哪里传递函数的返回值?

修改

如果我在将局部变量设置为值bind_empty_f之后调用该函数,则首先编译:

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

所以问题必须是与静态初始化编译器错误。

EDIT2

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

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

所以我想问题就变成了,这个符合标准的代码是什么?

1 个答案:

答案 0 :(得分: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

如果我们先执行bind_empty_f<float>,而test_func<float>会生成错误。

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

如果你直接调用它,类型尚未计算(似乎有一个缓存),那么推断出正确的类型,而我的test_func无法构建(因为它试图将3.14f转换为bind表达式并失败)。

这绝对是编译器的问题。您可以使用auto替换bind_empty_f中的std::decay_t<decltype(stuff_on_rhs)>来解决此问题。

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

live example compiling (wrongly)live example not compiling (correctly)