首页 > 解决方案 > 编译器不应该能够从概念中推断出模板参数吗?

问题描述

在下面的代码中,编译器不应该能够从概念中推断出模板参数吗?

#include <iostream>

template<typename T>
struct Bar;

template<typename F, typename T>
concept Foo = requires (F foo, Bar<T> bar)
{
    { foo.test(bar) } -> std::same_as<T>;
};

template<typename T>
struct Bar
{
    T value;

    template<Foo<T> F>
    T test(F foo)
    {
        return foo.test(*this);
    }
};

template<typename T>
struct FooBar
{
    T value;

    T test(Bar<T> bar)
    {
        return (value = bar.value) + bar.value;
    }
};

int main(void)
{
    Bar<float> b{ 1 };
    std::cout << b.test(FooBar{}) << std::endl; // Fails to deduce the template argument
    std::cout << b.test(FooBar<float>{}) << std::endl; // Compiles successfully
}

这是 MSVC 和 GCC 尚未实现的功能(两者都无法编译代码)吗?还是只是无效的 C++20 代码?如果是这样,为什么?模板参数不是float唯一可能的类型T吗?或者是否有一些我遗漏的替代方法可能会导致编译器产生歧义?

标签: c++templatesc++20template-argument-deductionc++-concepts

解决方案


编译器究竟要从什么推导出模板参数FooBar{}?您没有提供任何参数,也没有特殊的类模板推导指南,并且模板FooBar没有默认模板参数。

如果您期望通过使用表达式而不是表达式本身的固有属性(初始化程序中的参数,默认模板参数)来进行模板推导,那么这是错误的期望。

类模板参数推导完全基于提供给类对象的初始化程序的参数,就像函数模板参数推导完全基于提供给函数的参数一样。此后如何使用这两种表达方式都无关紧要。


推荐阅读