【问题标题】:how do i implement methods for a template class that can be either char or string?如何为可以是字符或字符串的模板类实现方法?
【发布时间】:2020-02-04 15:53:19
【问题描述】:

我有这门课

template <typename T>
class B{
    T x;
public:
    B(char c){
        if(typeid(x)==typeid(char)) x=c;
        else{
            string h;
            for(int i=0;i<10;i++) h.push_back(c);
            x=h;
        }
    }
};

这是一个示例类,如果 x 的类型是 char 我希望 x=c 而如果 x 是字符串我希望 x 是 [c]^10

然后我尝试创建两个对象:

int main(){
    B<string> a('f');
    B<char> b('g');     
}

当 i 对象 b 被实例化时,编译器会在第 10 行产生错误:

[Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'char' in assignment

我了解错误来自您无法将字符串分配给 char 的事实,但无论如何我都需要完成任务,我该怎么做?

【问题讨论】:

  • 这看起来更像是两个不同的类而不是模板。
  • 如果T 不是char 而不是std::string,会发生什么?
  • @MarekR:模板不必处理所有类型,即使std::uniform_real_distribution也只能处理float/double/long double
  • @Jarod42 我知道模板正在使用鸭子类型。问题的更多细节可以导致更合适的解决方案。

标签: c++ class templates


【解决方案1】:

对于 C++17,您可以使用 if constexpr:

template <typename T>
class B
{
    T x;
public:
    explicit B(char c)
    {
        if constexpr (std::is_same_v<T, char>) {
            x = c;
        } else {
            // static_assert(std::is_same_v<T, std::string>);
            x = std::string(10, c);
        }
    }
};

【讨论】:

  • 如果你是 C++17,std::is_same_v&lt;T, char&gt; 也可以使用。
【解决方案2】:

在 C++17 之前,这似乎是最简单的可能性:

#include <string>

template<class T>
class B {
    T x;
public:

    B(char c);
};

template<>
B<char>::B(char c) : x(c) {}

template<>
B<std::string>::B(char c) : x(std::string(c,10)) {}

int main() {
    B<char> a('a');
    B<std::string> b('b');
    //B<int> c('c'); // Linker error
}

【讨论】:

  • 如果您使用-std=c++17 指定C++17 作为编译器标志,则最高投票也将起作用,假设您的编译器支持C++17。我提出这一点是因为您的陈述暗示 C++17 解决方案不起作用;确实如此。不过,实际指定标准由您自己决定。
【解决方案3】:

如果 x 的类型是 char 我想要 x=c 而如果 x 是字符串我想要 x 是 [c]^10

一种方法是创建一个返回正确对象的函数模板。

// Declare the function template.
template <typename T> T make_data(char c);

Define specializations of the function template.
template <> char make_data<char>(char c)
{
   return c;
}

template <> make_data<std::string>(char c)
{
   return std::string(c, 10);
}

使用它们来实现B

template <typename T>
class B
{
   T x;
   public:
   B(char c) : x(make_data<T>(c)) {}
};

【讨论】:

  • 我无法定义更多的函数、方法或成员
  • @GuglielmoLaMastra,这是一个相当不寻常的约束。至少要知道,当你在外面的世界时,不太可能施加这样的限制。
【解决方案4】:

简单的老式模板专业化:

template <typename T>
class B
{
    T x;
public:
    explicit B(char c) : x(c)
    {}
};

template <>
B<std::string>::B(char c) : x(10, c)
{}

https://wandbox.org/permlink/5klGI0poD9mor4WY

【讨论】:

    猜你喜欢
    • 2019-06-14
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多