标签: function-templates

非类型函数模板参数

我正在阅读C++模板完整指南,并遇到了这个非类型函数模板参数代码(我添加了main()和除函数定义和调用之外的其他部分):

#include <vector>
#include <algorithm>
#include <iostream>

template <typename T, int value>
T add (T const & element){
  return element + value;
}

int main() {
  int a[] = {1,2,3,4};
  int length = sizeof (a) / sizeof (*a);
  int b[length];
  std::transform (a, a + length, b, (int(*)(int const &))add <int, 5>); //why?
  std::for_each (b, b + length, [](int const & value){ std::cout << value << '\n'; });
  return 0; 
}
Run Code Online (Sandbox Code Playgroud)

从书中读到为什么我们需要对函数调用进行类型转换后我才明白?

编辑:书中的解释:

add是一个函数模板,函数模板被认为是一组重载函数(即使集合只有一个成员).但是,根据当前标准,多组重载函数不能用于模板参数推导.因此,您必须转换为函数模板参数的确切类型:...

编译器:Ubuntu 10.10上的g ++ 4.5.1

c++ function-templates

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

对于auto stdMaxInt = std :: max <int>,类型推断失败;

使用GCC 4.8.4 g++ --std=c++11 main.cpp输出以下错误

error: unable to deduce ‘auto’ from ‘max<int>’
auto stdMaxInt = std::max<int>;
Run Code Online (Sandbox Code Playgroud)

这个代码

#include <algorithm>

template<class T>
const T& myMax(const T& a, const T& b)
{
    return (a < b) ? b : a;
}

int main()
{
    auto myMaxInt = myMax<int>;
    myMaxInt(1, 2);

    auto stdMaxInt = std::max<int>;
    stdMaxInt(1, 2);
}
Run Code Online (Sandbox Code Playgroud)

为什么它适用myMax但不适用std::max?我们能让它与之合作std::max吗?

c++ function-templates auto type-deduction template-instantiation

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

依赖于参数的查找和函数模板

这是一个例子:

#include <string>
#include <algorithm>
#include <memory>

using std::string;

int main()
{
    string str = "This is a string";

    // ok: needn't using declaration, ADL works
    auto it = find(str.begin(), str.end(), 'i');

    // error: why ADL doesn't work?
    std::shared_ptr<string> sp = make_shared<string>(str);
}
Run Code Online (Sandbox Code Playgroud)

当我试图编译这个程序时,编译器抱怨:

error: no template named 'make_shared'; did you mean 'std::make_shared'?
        std::shared_ptr<string> sp = make_shared<string>(str); // error...
                                     ^~~~~~~~~~~
                                     std::make_shared
Run Code Online (Sandbox Code Playgroud)

我猜第一个函数find不需要using声明,因为依赖于参数的lookup(ADL):编译器会搜索名称空间string(即std)的定义find.但对于第二个函数make_shared,它似乎ADL不起作用:我必须使用std::make_shared或 …

c++ templates function-templates argument-dependent-lookup

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

可变函数/非可变模板之间函数类型衰减的不一致性?

给定一个非可变函数模板:

template<class T>
void f(void(t)(T));
Run Code Online (Sandbox Code Playgroud)

还有一些简单的功能:

void f1(int);
void f2(char);
Run Code Online (Sandbox Code Playgroud)

这有效:

f(f1);
Run Code Online (Sandbox Code Playgroud)

类型t变成了void (*)(int).

但是,可变对应物:

template<class... T>
void f(void(...t)(T));

// call
f(f1, f2);
Run Code Online (Sandbox Code Playgroud)

不起作用.编译器(gcc&clang)抱怨不匹配的类型void(T)void (*)(int).见DEMO.

请注意,如果*明确添加,它可以正常工作:

template<class... T>
void f(void(*...t)(T));
Run Code Online (Sandbox Code Playgroud)

那么,为什么非可变参数可以衰减函数类型而可变参数不能?

c++ language-lawyer function-templates variadic-templates c++11

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

该函数调用是否应该模棱两可?

前几天,我偶然发现了这个问题,无法弄清楚哪个答案是正确的,或者都不能接受。

具体来说,我指的是对OtherFunction中的bar(T {})的调用。从我已经能够在编译器资源管理器上进行测试的角度来看,这个决定似乎有些分歧。当gcc和clang编译代码没有问题时,msvc和icc同意它是模棱两可的。

通过与参数相关的查找,隐藏的命名空间中的功能栏变得可见。此外,msvc / icc将全局命名空间中的bar声明视为候选,而gcc / clang则不这样做。似乎不应该考虑全局命名空间中的声明,因为它是在调用bar(T {})之后声明的,但是我不确定我是在正确读取不合格名称查找的规则还是标准是在这方面模棱两可。

https://godbolt.org/z/HAS-Cv

编辑:只要使用/ permissive-选项,看起来msvc已修复此问题(https://devblogs.microsoft.com/cppblog/two-phase-name-lookup-support-comes-to-msvc/

template <typename T>
inline void OtherFunction () {
    bar(T{});
}

namespace hidden {
    struct Foo {};
    inline void bar (Foo foo) {}
}

inline void bar (hidden::Foo foo) {}

void Function () {
    OtherFunction<hidden::Foo>();
}
Run Code Online (Sandbox Code Playgroud)

c++ function-templates name-lookup argument-dependent-lookup

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

功能模板专业化和Abrahams/Dimov示例

(我在这个问题上假设了亚伯拉罕/迪莫夫的例子.)

假设标题中有一些第三方代码,您无法修改:

template<class T> void f(T);    // (1) base template 1
template<class T> void f(T *);  // (2) base template 2
template<> void f<>(int *);     // (3) specialization of (2)
Run Code Online (Sandbox Code Playgroud)

问题是:

如果我按原样获得了上述声明,那么我现在可以将基础模板1专门用于T = int *(例如)的情况吗?

或者仅仅声明基本模板2意味着基本模板1不再是专用的(至少对于指针而言)?

c++ template-specialization function-templates

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

“用作非类型模板参数”是否使函数模板隐式实例化?

我想编写一个M接受不完整类型C作为模板参数的类模板。但我也希望C在最终定义时具有一些特征。

此代码是否有保证

  • 编译如果定义(标志),
  • 如果 !defined(FLAG) 编译失败?
template <auto> struct Dummy {};

template <typename C>
void check()
{
    static_assert(std::is_trivial_v<C>);
}

template <typename C>
struct M : Dummy<&check<C>>
{
    //static_assert(std::is_trivial_v<C>);//error: incomplete type
    C * p;
};

struct Test;
M<Test> m;

int main()
{
    return 0;
}

#if defined(FLAG)
struct Test {};
#else
struct Test { std::string non_trivial_member; };
#endif
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer function-templates implicit-instantiation non-type-template-parameter

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

可变参数模板函数对非可变参数的特殊化

我有一个函数模板,该函数至少接受一个参数并对其余参数执行一些格式化:

template <typename T, typename... ARGS>
void foo(T first, ARGS&&... args)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

当第一个参数是特定类型时,我希望它做不同的事情。我喜欢编译器选择这个特定的版本,其中其余的可变参数被忽略。所以我尝试了模板专业化:

template <>
void foo(const ICON* p)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

或者:

template <typename T, typename... ARGS>
void foo(const ICON* p, ARGS&&... args)
{
   // ...
}
Run Code Online (Sandbox Code Playgroud)

我还尝试了非模板化重载,但它总是选择第一个版本。

调用者代码应该根本不知道模板(遗留代码、向后兼容性废话等),因此它依赖于类型推导和如下调用:

MyClass fooMaker;
fooMaker.set("A", "B", 3.14, 42); // v1
fooMaker.set(pIcon);              // v2 (special)
Run Code Online (Sandbox Code Playgroud)

c++ templates function-templates overload-resolution variadic-templates

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

C++ 11 条件模板函数的别名

在 C++ 11 中,我想创建一个具有两个专业化的模板别名,每个专业化解析为不同的函数。

void functionA();
void functionB();

template<typename T = char>
using Loc_snprintf = functionA;

template<>
using Loc_snprintf<wchar_t> = functionB;
Run Code Online (Sandbox Code Playgroud)

所以我可以打电话给eg Loc_snprintf<>(),它决定了functionA()

显然似乎不可能(编译)。是否有一些最终简单的东西可以模仿它(也许使用类模板)?

c++ function-templates c++11 template-aliases

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

C++ 重载函数的地址

我有以下小的 C++ 代码示例,但我无法弄清楚为什么编译器以这种方式工作,尽管我花了很多时间研究 cppreference。我将不胜感激任何解释!神箭

#include <type_traits>

template<typename Tp>
struct depend_type
{
  constexpr static bool false_ = false;
};

template<typename Tp>
struct cont
{
  using x = void;

  static_assert(std::is_same_v<Tp, int>);
  // if uncomment, will be complie error -> 'cont<Tp>::x' instantiated with 'void (*p)(int) = func;'
//   static_assert(depend_type<Tp>::false_); 
};

template<typename Tp>
void func(Tp)
{
}

template<typename Tp>
typename cont<Tp>::x func(Tp);

int main(int /* argc */, char * /*argv*/[])
{
//  func(1); is ambiguous call
  void (*p)(int) = func; // why is …
Run Code Online (Sandbox Code Playgroud)

c++ function-templates overload-resolution template-meta-programming

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