标签: function-templates-overloading

为什么函数参数类型上的enable_if会影响重载解析?

请参阅 godbolt 上的代码

#include <iostream>
#include <cmath>
#include <type_traits>

template <typename T>
void f(T, T) // 1
{
    std::cout << "Primary\n";
}

template <typename T>
void f(T, std::enable_if_t<std::is_floating_point_v<T>, T>) // 2
{
    std::cout << "Special\n";
}

/*template <typename T>
std::enable_if_t<std::is_floating_point_v<T>> f(T, T) // 3
{
    std::cout << "Special\n";
}*/

int main()
{
    f(1.1, 1.1); // prints 'Primary'
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,std::enable_if应用于第二个函数模板重载的函数类型。该函数是通过 [T = double] 推导来调用的,并且它调用重载 1。但是,如果我注释掉重载 2 并将其替换为重载 3,那么编译器会抱怨该调用不明确。我也期望在第一种情况下,为什么编译器更喜欢重载 1 而不是 2?

我阅读了“函数模板重载”部分,但对我来说,重载 2 看起来更专业。

c++ language-lawyer enable-if function-templates-overloading

14
推荐指数
0
解决办法
77
查看次数

C++ 入门第 5 版。函数模板重载

C++ Primer一书中,有一个关于函数模板重载的例子:

// print any type we don't otherwise handle
template <typename T> string debug_rep(const T &t)
{
    cout << "debug_rep(T const&)\n";
    ostringstream ret; // see § 8.3 (p. 321)
    ret << t; // uses T's output operator to print a representation of t
    return ret.str(); // return a copy of the string to which ret is bound
}

// print pointers as their pointer value, followed by the object to which the pointer points
// NB: this …
Run Code Online (Sandbox Code Playgroud)

c++ template-argument-deduction function-templates-overloading

6
推荐指数
1
解决办法
76
查看次数

具有不同参数类型的受约束函数模板与无约束函数模板

在下面的两个模板函数中,我们尝试了更多的约束:

template<typename T>
concept SmallVar = (sizeof(T) <= sizeof(int));

void print(SmallVar auto t) { // 1
    std::cout << t << std::endl;
}

void print(const auto& t) {   // 2 
    std::cout << t << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

当使用 int 调用时,Clang 和 GCC 有所不同:

int main() {
    print(6);  // clang accepts and prefers 1, gcc sees here ambiguity
}
Run Code Online (Sandbox Code Playgroud)

哪一个是正确的?

代码: https: //godbolt.org/z/x71zjzoTa

c++ templates c++20 function-templates-overloading

6
推荐指数
1
解决办法
107
查看次数

从 cppreference 理解 std::is_base_of 可能的实现

这里我们有is_base_of来自cppreference.com的模板实现:

namespace details {
     template <typename B>
     std::true_type test_pre_ptr_convertible(const B*);      //1
     template <typename>
     std::false_type test_pre_ptr_convertible(const void*);  //2

     template <typename, typename>
     auto test_pre_is_base_of(...)->std::true_type;          //3
     template <typename B, typename D>
     auto test_pre_is_base_of(int) ->
         decltype(test_pre_ptr_convertible<B>(static_cast<D*>(nullptr))); 
 }

template <typename Base, typename Derived>
 struct is_base_of :
     std::integral_constant<
     bool,
     std::is_class<Base>::value&& std::is_class<Derived>::value&&
     decltype(details::test_pre_is_base_of<Base, Derived>(0))::value
     > { };
Run Code Online (Sandbox Code Playgroud)

还有一些私有继承:

class A {};
class B : A {};
Run Code Online (Sandbox Code Playgroud)

is_base_of<A,B>::value给出 true 和声明号。3 是最佳匹配。声明编号 1 作为候选者失败(传递了一个指向私有子类对象的指针)并且声明号。2 被忽略。但为什么?不是void*每个指针类型都能很好匹配吗?如果声明没有。3 未提供代码将无法编译。我的问题是为什么声明没有。3 需要提供此代码才能成功编译吗?为什么声明没有。1 和没有。2个还不够?

c++ overloading template-meta-programming function-templates-overloading

6
推荐指数
1
解决办法
197
查看次数

是什么导致这两个函数模板之间的重载失败?

下面是一个非常简短的例子。

#include <utility>

template<typename T, typename = void>
struct A {};

template<typename T, typename U>
void f(A<std::pair<T,U>>) {}

template<typename U>
void f(A<std::pair<int,U>, std::enable_if_t<std::is_same_v<int,U>>>) {}

int main() {
  A<std::pair<int, int>> x;
  f(x);
}
Run Code Online (Sandbox Code Playgroud)

错误很明显

uffa.cpp: In function ‘int main()’:                                                                                                                                                                                                                           
uffa.cpp:22:4: error: call of overloaded ‘f(A<std::pair<int, int> >&)’ is ambiguous                                                                                                                                                                           
   22 |   f(x);                                                                                                                                                                                                                                                
      |   ~^~~                                                                                                                                                                                                                                                 
uffa.cpp:10:6: note: candidate: ‘void f(A<std::pair<_T1, _T2> >) [with T = int; U = int]’                                                                                                                                                                     
   10 | void f(A<std::pair<T,U>>) {}                                                                                                                                                                                                                           
      |      ^                                                                                                                                                                                                                                                 
uffa.cpp:18:6: note: candidate: ‘void f(A<std::pair<int, U>, …
Run Code Online (Sandbox Code Playgroud)

c++ sfinae language-lawyer enable-if function-templates-overloading

5
推荐指数
1
解决办法
190
查看次数

Template deduction depends on another template deduction

Since std::format isn't supported everywhere, and I didn't want another large dependency like fmt, I wanted to quickly roll my own to_string solution for a number of types. The following is the code.

#include <ranges>
#include <string>
#include <concepts>

template<typename Type>
constexpr std::string stringify(const Type &data) noexcept;

template<typename Type> requires std::integral<Type>
constexpr std::string stringify(const Type &data) noexcept {
    return std::to_string(data);
}

template<typename Type>
constexpr std::string stringify_inner(const Type &data) noexcept {
    return stringify(data);
}

template<typename Type> requires std::ranges::range<Type>
constexpr std::string …
Run Code Online (Sandbox Code Playgroud)

c++ algorithm templates c++20 function-templates-overloading

5
推荐指数
1
解决办法
182
查看次数

C++ 函数模板重载:空大括号 vs 显式 int

下面有一些非常基本的 C++ 函数模板重载解析示例(从实际代码中最小化)

struct S {
    S() {}
    S(int) {}
};

template <typename T = S>
void foo(T x) { std::cout << "S" << std::endl; }

template <>
void foo<S>(S x) { std::cout << "S spc" << std::endl; }

int main() {
    foo({});
    foo(0);
}
Run Code Online (Sandbox Code Playgroud)

这里我们有两种情况。在第一种情况下编译器应默认初始化某些东西(如 S)在第二种情况下将 int 转换为某些东西(如 S)

Godbolt 上的活生生的例子

我相信在这两种情况下,专业化都会赢得重载,因为专业化完全匹配,并且通过偏序 [temp.deduct.partial] 比主模板更专业

但是这个例子中的 clang 11 和 gcc 10.2 都同意在第二种情况下主模板获胜。这是两个编译器中的错误还是(可能)我对 C++ 标准不了解?

c++ c++20 function-templates-overloading

3
推荐指数
1
解决办法
61
查看次数

如何在函数重载中推导 lambda 的模板参数?

我应该如何修改我当前的函数签名

template<class TypeData,typename TypeFunc1 = Identity,typename TypeFunc2>
bool isPrime(const TypeData& n,TypeFunc1 calcSqrt = {},TypeFunc2 isDivisible = [](const TypeData& a,const TypeData& b) {return a%b==0;},const bool debug = false)
Run Code Online (Sandbox Code Playgroud)

为了被调用

auto fSqrt = [](decltype(n) v) {return std::sqrt(static_cast<float>(v));};
std::cout<<(isPrime(n,fSqrt)?"Positive":"Negative")<<'\n';
Run Code Online (Sandbox Code Playgroud)

Visual Studio 2019 提供

C2783 'bool isPrime(const TypeData &,TypeFunc1,TypeFunc2,const bool)':无法推导出 'TypeFunc2' 的模板参数

不过,没有 一切都很好TypeFunc2 isDivisible = [](const TypeData& a,const TypeData& b) {return a%b==0;}

传递默认 lambda 的正确语法是什么?
请帮助我。

c++ lambda c++17 function-templates-overloading

0
推荐指数
1
解决办法
483
查看次数