【问题标题】:selecting appropriate copy-constructor based on template parameters根据模板参数选择合适的复制构造函数
【发布时间】:2015-10-27 08:52:57
【问题描述】:

我想根据模板参数值选择成员函数(复制构造函数)的实现。我想有两种方法:SFINAE 和模板偏特化。

最后一个应该是这样的:

#include <iostream>

template<typename A, bool sw>
struct B
{
    B() {}
    B(const B &b);
};

template<typename A>
B<A, false>::B(const B<A, false> &b)
{
    std::cout << "false\n";
}

template<typename A>
B<A, true>::B(const B<A, true> &b)
{
    std::cout << "true\n";
}

int main()
{
}

无法编译:nested name specifier 'B&lt;A, false&gt;::' for declaration does not refer into a class, class template or class template partial specialization

SFINAE 方法也失败了:

#include <type_traits>
#include <iostream>

template<typename A, bool sw>
struct B
{
    B() {}

    template<typename U = typename std::enable_if<sw, B>::type>
    B(const U &b)
    {
        std::cout << "true\n";
    }

    template<typename U = typename std::enable_if<!sw, B>::type>
    B(const U &b)
    {
        std::cout << "false\n";
    }
};

int main()
{
    {
        B<int, true> b;
        auto bc = b; // cout << true
    }
    {
        B<int, false> b;
        auto bc = b; // cout << false
    }
}

这里的编译错误是constructor cannot be redeclaredno type named 'type' in 'std::enable_if&lt;false, B&lt;int, false&gt; &gt;'; 'enable_if' cannot be used to disable this declaration

有没有办法解决问题或者根据模板参数选择合适的复制构造函数?

【问题讨论】:

  • 你不能只对一个类(或结构)的成员进行部分特化,你需要对整个类进行部分特化。
  • 作为记录,这里的问题之一是您不能拥有模板化的复制构造函数(除了在您的情况下两个签名相同,这可以修复) ,因为隐式生成的复制构造函数总是在重载决议中获胜

标签: c++ templates c++11 sfinae


【解决方案1】:
template <typename A, bool sw>
struct B
{
    B() = default;

    B(const B& b) : B(b, std::integral_constant<bool, sw>{}) {}

private:
    B(const B& b, std::true_type)
    {
        std::cout << "true\n";
    }

    B(const B& b, std::false_type)
    {
        std::cout << "false\n";
    }
};

DEMO

【讨论】:

    【解决方案2】:

    正如@Joachim Pileborg 在评论中所说,你不能只专注于一个班级的成员,你必须专注于整个班级。所以你的部分专业化看起来像这样:

    template<typename A, bool sw>
    struct B
    {
        B() {}
        B(const B &b);
    };
    
    //Specialize when sw is false
    template<typename A>
    struct B<A, false>
    {
         //The constructor in the specialized struct print false
         B(const B &b)
         {
            std::cout << "false\n";
         }
    };
    
    //Specialize when sw is true
    template<typename A>
    struct B<A, true>
    {
        //The constructor in the specialized struct print true
        B(const B &b)
        {
            std::cout << "true\n";
        }
    };
    

    @Piotr Skotnicki 为您提供了 SFINAE 的最佳解决方案

    【讨论】:

    • “因为你不能重新声明构造函数” 你可以根据需要重新声明多次(通过更改签名,比如添加一个虚拟模板参数,如typename = void) ,这里的问题是,即使它是固定的,隐式生成的复制构造函数总是会被选为更好的候选者(因为它是非模板)
    • 你是对的,我应该在我的回答中说你不能重新声明具有相同签名的构造函数。
    【解决方案3】:

    我知道这是一个最小的例子,但是有什么问题

    B(const B& b) {
      if(sw) {
        std::cout << "true\n";
      } else {
        std::cout << "false\n";
      }
    }
    

    【讨论】:

    • 是的,它解决了问题。但在我的情况下,复制构造函数使用或不使用(取决于sw)构造函数委托。
    猜你喜欢
    • 2017-09-27
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多