C++ 函数调用概念不明确

Ale*_*eat 1 c++ templates c++-concepts c++20

我有一个 C++ 宏,我想用它来调用一个重载的函数模板。我希望这些函数模板之一仅接受浮点值,而另一个函数模板将接受其他所有内容。

以下是我使用 C++ 20 在https://cpp.sh/中运行的代码:

#include <iostream>
#include <string>
#include <vector>
#include <type_traits>
#include <concepts>

template< typename T>
concept NotFloatingPoint = requires
{
    !std::is_same_v<T, double> || !std::is_same_v<T, float>;
};

template< NotFloatingPoint T, NotFloatingPoint U, bool isDistanceType_ = false >
void ProcConstantConfigForce( T& value_ )
{
    std::cout << "Inside ProcConstantConfigForce()\n";
    std::cout << value_;
}

template< typename T>
concept FloatingPoint = requires
{
    std::is_same_v<T, double> || std::is_same_v<T, float>;
};

template< FloatingPoint T, FloatingPoint U, bool isDistanceType_ = false >
void ProcConstantConfigForce( T& value_ )
{
    std::cout << "Inside ProcConstantConfigForce() for doubles\n";
    std::cout << value_;

    if ( isDistanceType_ )
    {
        value_ *= 1.5;
    }
}

#define FORCE_CONSTANT( constant_, isDistanceType_ ) ProcConstantConfigForce< decltype( constant_ ), decltype( constant_ ), isDistanceType_ >

int main()
{
  double val = 1.0;
  FORCE_CONSTANT(1.0, true)(val);
  std::cout << "Updated val: " << val;
}
Run Code Online (Sandbox Code Playgroud)

然而,编译器抱怨它不明确:

main.cpp:43:3: error: call to 'ProcConstantConfigForce' is ambiguous
  FORCE_CONSTANT(1.0, true)(val);
  ^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:38:54: note: expanded from macro 'FORCE_CONSTANT'
#define FORCE_CONSTANT( constant_, isDistanceType_ ) ProcConstantConfigForce< decltype( constant_ ), decltype( constant_ ), isDistanceType_ >
                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:14:6: note: candidate function [with T = double, U = double, isDistanceType_ = true]
void ProcConstantConfigForce( T& value_ )
     ^
main.cpp:27:6: note: candidate function [with T = double, U = double, isDistanceType_ = true]
void ProcConstantConfigForce( T& value_ )
     ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

我发现我可以使用constexprstd::floating_point概念来解决我的问题,并且只需使用单个函数模板。但是,我特别想知道为什么编译器抱怨它不明确,因为很明显只有一个函数应该用于浮点值,那么为什么当概念应该限制它时它会尝试实例化第一个函数的模板呢?

感谢您的帮助。

Bri*_*ian 5

您的代码有两个问题。第一的,

template< typename T>
concept NotFloatingPoint = requires
{
    !std::is_same_v<T, double> || !std::is_same_v<T, float>;
};
Run Code Online (Sandbox Code Playgroud)

不做你认为它做的事情:requires { expr; }检查是否expr是一个有效的表达式,而不是是否expr为真。所以你应该将其重写为

template< typename T>
concept NotFloatingPoint = !std::is_same_v<T, double> || !std::is_same_v<T, float>;
Run Code Online (Sandbox Code Playgroud)

但它仍然是不正确的。现在,它检查以下两件事之一是否为真:Tis notdoubleTis not float。这意味着即使Tdouble,它仍然满足,NotFloatingPoint因为double不是float。永远不可能NotFloatingPoint是假的。正确的定义是:

template< typename T>
concept NotFloatingPoint = !std::is_same_v<T, double> && !std::is_same_v<T, float>;
Run Code Online (Sandbox Code Playgroud)

或者更简单的方法可能是:

template< typename T>
concept FloatingPoint = std::is_same_v<T, double> || std::is_same_v<T, float>;

template <typename T>
concept NotFloatingPoint = !FloatingPoint<T>;
Run Code Online (Sandbox Code Playgroud)