这段代码有什么问题?
#include <map>
template<typename T>
struct TMap
{
typedef std::map<T, T> Type;
};
template<typename T>
T test(typename TMap <T>::Type &tmap_) { return 0.0; }
int _tmain(int argc, _TCHAR* argv[])
{
TMap<double>::Type tmap;
tmap[1.1] = 5.2;
double d = test(tmap); //Error: could not deduce template argument for T
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我创建了两个简单的函数来获取模板参数和一个定义类型的空结构:
//S<T>::type results in T&
template <class T>
struct S
{
typedef typename T& type;
};
//Example 1: get one parameter by reference and return it by value
template <class A>
A
temp(typename S<A>::type a1)
{
return a1;
}
//Example 2: get two parameters by reference, perform the sum and return it
template <class A, class B>
B
temp2(typename S<A>::type a1, B a2)//typename struct S<B>::type a2)
{
return a1 + a2;
}
Run Code Online (Sandbox Code Playgroud)
参数类型应用于struct S以获取引用.我用一些整数值调用它们但编译器无法推断出参数:
int main()
{
char c=6;
int …
Run Code Online (Sandbox Code Playgroud) 假设以下情况:
类型A
和类型B
,B
可以隐式转换为A
但反之则是不真实的.
我有一个功能
template<class T>
void do_stuff(T a, T b);
Run Code Online (Sandbox Code Playgroud)
我想这样调用所述函数:
do_stuff(A{}, B{});
Run Code Online (Sandbox Code Playgroud)
这里的问题是编译器无法推断出类型,而是说:
template argument deduction/substitution failed
Run Code Online (Sandbox Code Playgroud)
我可以这样调用我的函数:
do_stuff<A>(A{}, B{});
Run Code Online (Sandbox Code Playgroud)
但这对用户来说更烦人.
或者我可以做这样的事情:
template<class T, class M>
void do_stuff(T a, M b);
Run Code Online (Sandbox Code Playgroud)
但是b继续以它的快乐方式成为B类(具有先前的调用).
理想情况下,我想要像:
template<class T, class M = T>
void do_stuff(T a, M b);
Run Code Online (Sandbox Code Playgroud)
要么:
template<class T@INSERT MAGIC SO THAT T IS DEDUCED AS BEING THE TYPE OF ARGUMENT NR 1@>
void do_stuff(T a, T b);
Run Code Online (Sandbox Code Playgroud)
这样的事情可能吗?
c++ templates metaprogramming template-meta-programming c++17
我想将一个可调用的(std::function
对象)传递给一个类Foo
.callable指的是具有任意参数的另一个类的成员方法,因此Foo
必须是可变参数模板.考虑以下代码:
struct Bar {
void MemberFunction(int x) {}
};
template<typename ...Args>
class Foo {
public:
Foo(std::function<void(Bar*, Args...)> f) {}
};
int main() {
Foo<int> m1(&Bar::MemberFunction);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译好了.现在我想写一个工厂函数MakeFoo()
返回一个unique_ptr
到一个Foo
对象:
template<typename ...Args>
std::unique_ptr<Foo<Args...>> MakeFoo(std::function<void(Bar*, Args...)> f) {
return std::make_unique<Foo<Args...>>(f);
}
Run Code Online (Sandbox Code Playgroud)
通过调用使用此功能
auto m2 = MakeFoo<int>(&Bar::MemberFunction);
Run Code Online (Sandbox Code Playgroud)
在main中,给出了以下编译器错误:
functional.cc: In function ‘int main()’:
functional.cc:21:50: error: no matching function for call to ‘MakeFoo(void (Bar::*)(int))’
auto m2 = MakeFoo<int>(&Bar::MemberFunction);
^
functional.cc:15:35: note: candidate: …
Run Code Online (Sandbox Code Playgroud) 我正在尝试将迭代器作为模板参数传递给模板方法,但编译器抱怨:
error C2783: 'void Test::Assert(std::vector<T>::const_iterator)':
could not deduce template argument for 'T'
Run Code Online (Sandbox Code Playgroud)
产生错误的代码是:
#include "stdafx.h"
#include <iostream>
#include <vector>
class Test
{
public:
template <typename T>
void Assert(typename std::vector<T>::const_iterator it)
{
std::cout << *it << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Test test;
std::vector<double> myVec;
test.Assert(myVec.cbegin());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我猜有一种简单的方法可以使这项工作,因为大多数std算法可以从迭代器中推断出类型.
为什么编译器无法推导出模板参数std::forward
?
我的意思是:
#include <memory>
#include <iostream>
struct X{};
struct A{
A( const X& ) { std::cout << "cpy ctor\n"; }
A( X&& ) { std::cout << "move ctor\n"; }
};
X foo() { return {}; }
template<typename T,typename Arg>
T* factory( Arg&& a )
{
return new T(std::forward(a));
// ----------^^^^^^^^^^^^^^^ error: can't deduce template parameter
}
int main()
{
factory<A>(foo());
}
Run Code Online (Sandbox Code Playgroud)
我知道这是一个设计选择(由于std::remove_reference
在定义中std::forward
),以避免用户忘记指定类型.我不能得到的是:为什么它的实施方式可以防止扣除?为什么编译器不只是将forward
模板参数推断为Arg
.
我正在做一些看起来像这样的包装器:
#include <iostream>
template<class T, class Value>
void Apply(void (T::*cb)(Value), T* obj, Value v)
{
(obj->*cb)(v);
}
class Foo
{
public:
void MyFunc(const int& i)
{
std::cout << i << std::endl;
}
const int& GetValue()
{
return i_;
}
private:
int i_ = 14;
};
int main()
{
Foo f;
Apply(&Foo::MyFunc, &f, f.GetValue());
}
Run Code Online (Sandbox Code Playgroud)
我收到这个错误:
Apply
:找不到匹配的重载函数. void Apply(void (__thiscall T::* )(Value),T *,Value)
:模板参数Value
不明确,可能是int
或const int &
. void Apply(void (__thiscall T::* )(Value),T *,Value)
:无法推断Value …
c++ templates ambiguous ambiguous-call template-argument-deduction
在我的代码使用模板图像类Image<T>
与组合std::shared_ptr
.这些图像指针应该被传递给各种图像处理功能,其中一些功能与图像类型无关.考虑以下定义Image<T>
,以及两个处理函数function1()
和function2()
.
#include <memory>
template <typename T>
struct Image
{
typedef std::shared_ptr<Image<T>> Ptr;
};
template <typename T>
void function1 (typename Image<T>::Ptr image) {}
template <typename T>
void function2 (std::shared_ptr<Image<T>> image) {}
Run Code Online (Sandbox Code Playgroud)
虽然function1()
并且function2()
有效地具有相同的签名,但是function1()
更容易阅读并隐藏指针如何实现的细节.但是,我在function1()
没有明确指定模板类型的情况下无法调用.请考虑以下代码:
int main (void)
{
Image<int>::Ptr image = std::make_shared<Image<int>>();
function1(image); // Does NOT compile
function1<int>(image); // Does compile
function2(image); // Does compile
return 0;
}
Run Code Online (Sandbox Code Playgroud)
第一次调用导致编译错误:
example.cc: In function 'int main()':
example.cc:18:19: …
Run Code Online (Sandbox Code Playgroud) 最小的例子相当短:
\n#include <iostream>\n#include <array>\n#include <type_traits>\n\nstruct Foo{\n //template <class C>\n //Foo(C col, typename std::enable_if<true,C>::type* = 0){\n // std::cout << "optional argument constructor works" << std::endl;\n //}\n template <class C>\n Foo(typename std::enable_if<true, C>::type col){\n std::cout << "no optional argument constructor works NOT" << std::endl;\n }\n};\n\nint main()\n{\n auto foo = Foo(std::array<bool,3>{0,0,1});\n}\n
Run Code Online (Sandbox Code Playgroud)\n第一个构造函数按预期工作。但是第二个构造函数无法编译,我得到
\n\n\n错误:没有匹配的函数可调用 \xe2\x80\x98Foo::Foo(std::array)\xe2\x80\x99
\n
然而给出的解释
\n\n\n注意:模板参数推导/替换失败
\n
没有帮助,正如std::enable_if<true, C>::type
应该的C
那样,两个构造函数中的第一个参数对于编译器来说应该看起来完全相同。我显然错过了一些东西。为什么编译器的行为不同?对于不使用可选参数的构造函数和enable_if,是否有其他解决方案?
完整的错误消息:
\nmain.cpp:18:45: error: no matching function for call to …
Run Code Online (Sandbox Code Playgroud) 请考虑以下示例.
#include <type_traits>
#include <iostream>
using namespace std;
template <typename T_>
using Integral = typename std::enable_if<std::is_integral<T_>::value,T_>::type;
template <typename T_>
using NotIntegral = typename std::enable_if<!std::is_integral<T_>::value, T_>::type;
template <typename T_>
void printIt(const Integral<T_> &value) { cout << "Integral == " << value << endl; }
template <typename T_>
void printIt(const NotIntegral<T_> &value) { cout << "Non Integral == " << value << endl; }
template <typename T_>
void foo(const T_ &value) { printIt<T_>(value); }
int main(int argc, char** argv)
{
printIt<int>(66); //Must …
Run Code Online (Sandbox Code Playgroud) c++ ×10
templates ×9
c++11 ×4
template-argument-deduction ×2
ambiguous ×1
c++17 ×1
enable-if ×1
parameters ×1
type-traits ×1