简体   繁体   English

如何调用模板类型

[英]How to call templated type with

I am trying to create a template function that has two different implementations based on a template argument. 我正在尝试创建一个模板函数,它具有两个基于模板参数的不同实现。 While the first one is specific for I/O manipulators and the second one is for any general case. 第一个是针对I / O操纵器的,第二个针对任何一般情况。

template <typename T>
typename std::enable_if<
            std::is_same<decltype(std::setw), T>::value>::type
foo(T& t){
        cout << "enabled" << std::endl;
}

template <typename T>
void foo(T& t){
        cout << "Normal" << std::endl;
}

template <typename... Ts>
void foohelper(Ts... t){
        foo(t...);
}
int main(){
        foohelper(std::setprecision(3)); // It should print enabled, but printing Normal
}

Currently it is not doing what I am trying to implement. 目前它没有做我想要实现的。 How can I fix it? 我该如何解决?

You don't need to use enable_if - just specialise the template below the main definition of template foo . 您不需要使用enable_if - 只需在template foo的主要定义下面专门化template foo

template <>
void foo<decltype(std::setw(0))>(decltype(std::setw(0))& t)
{
        cout << "enabled" << std::endl;
}

The return type of these functions are unspecified . 这些函数的返回类型未指定 That means you can't use type_traits to compare them. 这意味着你不能使用type_traits来比较它们。 As an example, here's libcxx : 举个例子,这是libcxx

// Definitions omitted
T2 setiosflags (ios_base::fmtflags mask);
T3 setbase(int base);
template<charT> T4 setfill(charT c);
T5 setprecision(int n);
T6 setw(int n);

T5 , T6 , etc. refer to __imo_t4 etc., an internal structure that does the actual work of the manipulator. T5T6等指的是__imo_t4等,它是执行机械手实际工作的内部结构。 Since they all have different return types, the functions have different types. 由于它们都具有不同的返回类型,因此功能具有不同的类型。 Hence they'll all be different. 因此他们都会有所不同。

You can use SFINAE by comparing the return type of the function std::setprecision . 您可以通过比较函数std::setprecision的返回类型来使用SFINAE。 Since the return type is unspecified, you will need decltype and std::declval . 由于返回类型未指定,因此您需要decltypestd::declval

Here's the solution: 这是解决方案:

template <typename T, typename std::enable_if<std::is_same<decltype(std::setprecision(std::declval<int>())), typename std::decay<T>::type>::value, int>::type = 0>
void foo(T&& t) {
    cout << "enabled" << std::endl;
}

Here I changed T& to T&& so it accept any kind of reference. 在这里,我将T&改为T&&因此它接受任何类型的参考。 That remove the use of your foohelper . 删除你的foohelper的使用。

Furthermore, is the type comparison, I decay the type T , since the comparison won't work if one of the type is a reference type, because T& is not the same as T . 此外,是类型比较,我衰减类型T ,因为如果其中一个类型是引用类型,则比较将不起作用,因为T&T The use of std::decay will effectively remove the reference. 使用std::decay将有效地删除引用。

Notice that I moved the SFINAE construct inside the template declaration. 请注意,我在模板声明中移动了SFINAE构造。 This is to keep SFINAE away from the return type. 这是为了使SFINAE远离返回类型。 The use of non type template parameter defaulted to 0 won't affect the use of the function and will ensure that no one can effectively bypass the SFINAE check. 使用默认为0的非类型模板参数不会影响函数的使用,并且将确保没有人能够有效地绕过SFINAE检查。

Edit: 编辑:

You can replace std::declval<int>() with 0 in your case. 在您的情况下,您可以将std::declval<int>()替换为0 I was just willing to show how you can use this tool to replace actual value. 我只是愿意展示如何使用这个工具来取代实际价值。 There are a lot of cases where you can't have values. 在很多情况下你不能拥有价值观。

如何显式调用运算符 &lt; 的模板化重载<!--?</div--><div id="text_translate"><p> 考虑以下用于重载class A的operator&lt;&lt;的示例代码:</p><pre> #include &lt;iostream&gt; class A { template &lt;typename T&gt; friend A &amp;operator&lt;&lt;(A &amp;a, const T &amp;t) { std::cout &lt;&lt; t &lt;&lt; std::endl; return a; } friend A &amp;operator&lt;&lt;(A &amp;a, const std::string &amp;t) { return operator&lt;&lt;&lt;std::string&gt;(a, t + "x"); } };</pre><p> 我的意图是第二个运算符显式调用第一个运算符。</p><p> 但是,在 g++ 7.4 中,这失败了</p><blockquote><p>在 function 'A&amp; operator&lt;&lt;(A&amp;, const string&amp;)' 中:<br> 错误:'operator&lt;&lt;' 未定义<br>返回运算符&lt;&lt;&lt;std::string&gt;(a, t + "x");<br> ^~<br> 错误:“&gt;”标记之前的预期主表达式<br>返回运算符&lt;&lt;&lt;std::string&gt;(a, t + "x");<br> ^</p></blockquote><p> 然而,我不明白为什么这不应该编译。</p><p> <a href="https://godbolt.org/z/ckKDXH" rel="nofollow noreferrer">这是godbolt中的代码。</a></p></div> - How to explicity call a templated overload of operator <<?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何以元组 b 作为参数为元组(充当类型列表)中的每种类型调用模板化 function - How to call a templated function for each type in a tuple (acting as type list) with tuple b as argument 如何使用指向模板化类型的指针 - How to use a pointer to a templated type 如何通过 C++ 中模板化类型的子类传递模板化 function 参数? - How to pass a templated function parameter with a subclass of the templated type in C++? 如何使用模板中的参数调用模板化函数? - How to call a templated function with a parameter in the template? 如何从模板化基类调用构造函数 - How to call constructor from templated baseclass 如何在模板项成员上显式调用析构函数 - How to explicitly call the destructor on a templated item member 如何调用模板化类的析构函数? - How can I call a destructor of a templated class? 如何显式调用运算符 &lt; 的模板化重载<!--?</div--><div id="text_translate"><p> 考虑以下用于重载class A的operator&lt;&lt;的示例代码:</p><pre> #include &lt;iostream&gt; class A { template &lt;typename T&gt; friend A &amp;operator&lt;&lt;(A &amp;a, const T &amp;t) { std::cout &lt;&lt; t &lt;&lt; std::endl; return a; } friend A &amp;operator&lt;&lt;(A &amp;a, const std::string &amp;t) { return operator&lt;&lt;&lt;std::string&gt;(a, t + "x"); } };</pre><p> 我的意图是第二个运算符显式调用第一个运算符。</p><p> 但是,在 g++ 7.4 中,这失败了</p><blockquote><p>在 function 'A&amp; operator&lt;&lt;(A&amp;, const string&amp;)' 中:<br> 错误:'operator&lt;&lt;' 未定义<br>返回运算符&lt;&lt;&lt;std::string&gt;(a, t + "x");<br> ^~<br> 错误:“&gt;”标记之前的预期主表达式<br>返回运算符&lt;&lt;&lt;std::string&gt;(a, t + "x");<br> ^</p></blockquote><p> 然而,我不明白为什么这不应该编译。</p><p> <a href="https://godbolt.org/z/ckKDXH" rel="nofollow noreferrer">这是godbolt中的代码。</a></p></div> - How to explicity call a templated overload of operator <<? 如何使用SFINAE分配给模板化的呼叫操作员 - How to dispatch to templated call operator using SFINAE 如何区分存储在模板化类中的类型 - How to distinguish the type stored in a templated class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM