我試圖推廣我的課使用基於策略的設計,似乎gcc沒有看到在基類中實現的純虛函數的實現。這裏有一個例子:GCC沒有看到通過多繼承實現
#include <iostream>
template <typename ReturnValue, template <typename> class... AccessPolicies>
struct testInterface : public AccessPolicies<ReturnValue>::interface...
{
};
template <typename DataClass, typename ReturnValue, template <typename> class... AccessPolicies>
struct testImplementation : public DataClass,
public testInterface< ReturnValue, AccessPolicies... >,
public AccessPolicies<ReturnValue>::template implementation<DataClass>...
{
};
template < typename ReturnValue >
struct GetByIndex;
template <>
struct GetByIndex<std::string>
{
class interface
{
public:
virtual std::string operator[](size_t) = 0;
protected:
virtual ~interface() = default;
};
template <class DataClass>
class implementation
{
public:
virtual std::string operator[](size_t)
{
return "test by index";
}
protected:
virtual ~implementation() = default;
};
};
template < typename ReturnValue >
struct GetByName;
template <>
struct GetByName<std::string>
{
class interface
{
public:
virtual std::string operator[](std::string) = 0;
protected:
virtual ~interface() = default;
};
template <class DataClass>
class implementation
{
public:
virtual std::string operator[](std::string)
{
return "test by string";
}
protected:
virtual ~implementation() = default;
};
};
struct data
{
};
int main()
{
testImplementation< data, std::string, GetByIndex, GetByName> test;
testInterface< std::string, GetByIndex, GetByName >& Test = test;
std::cout << Test[5] << std::endl;
return 0;
}
錯誤我越來越有:
..\nienazwany\main.cpp: In function 'int main()':
..\nienazwany\main.cpp:78:67: error: cannot declare variable 'test' to be of abstract type 'testImplementation<data, std::basic_string<char>, GetByIndex, GetByName>'
testImplementation< data, std::string, GetByIndex, GetByName> test;
^
..\nienazwany\main.cpp:10:8: note: because the following virtual functions are pure within 'testImplementation<data, std::basic_string<char>, GetByIndex, GetByName>':
struct testImplementation : public DataClass,
^
..\nienazwany\main.cpp:53:29: note: virtual std::string GetByName<std::basic_string<char> >::interface::operator[](std::string)
virtual std::string operator[](std::string) = 0;
^
..\nienazwany\main.cpp:26:29: note: virtual std::string GetByIndex<std::basic_string<char> >::interface::operator[](size_t)
virtual std::string operator[](size_t) = 0;
^
..\nienazwany\main.cpp:81:24: error: request for member 'operator[]' is ambiguous
std::cout << Test[5] << std::endl;
^
..\nienazwany\main.cpp:53:29: note: candidates are: virtual std::string GetByName<std::basic_string<char> >::interface::operator[](std::string)
virtual std::string operator[](std::string) = 0;
^
..\nienazwany\main.cpp:26:29: note: virtual std::string GetByIndex<std::basic_string<char> >::interface::operator[](size_t)
virtual std::string operator[](size_t) = 0;
有兩個問題的,我不完全得到:
- 編譯器似乎不考慮
AccessPolicy<ReturnType>::implementation<DataClass>...
即使函數簽名完全相同,也要執行AccessPolicy<ReturnType>::interface...
。 - 編譯器無法解析哪個運算符[]我打電話,即使它們都有不同的參數,我清楚地調用size_t(數字不能隱式轉換爲字符串)。
任何想法爲什麼會發生這種情況?
我的猜測是,即使我直接從「接口」和「實現」繼承,成員函數以某種方式結束於不同的命名空間。如果這是正確的,我該如何解決這個問題?
編輯:加入剝離模板的上述例子中,按請求
#include <iostream>
class GetByIndexInterface
{
public:
virtual std::string operator[](size_t) = 0;
protected:
virtual ~GetByIndexInterface() = default;
};
class GetByIndexImplementation
{
public:
virtual std::string operator[](size_t)
{
return "test by index";
}
protected:
virtual ~GetByIndexImplementation() = default;
};
class GetByNameInterface
{
public:
virtual std::string operator[](std::string) = 0;
protected:
virtual ~GetByNameInterface() = default;
};
class GetByNameImplementation
{
public:
virtual std::string operator[](std::string)
{
return "test by string";
}
protected:
virtual ~GetByNameImplementation() = default;
};
struct data
{
};
struct testInterface : public GetByIndexInterface,
public GetByNameInterface
{
};
struct testImplementation : public data,
public testInterface,
public GetByIndexImplementation,
public GetByNameImplementation
{
};
int main()
{
testImplementation test;
testInterface& Test = test;
std::cout << Test[5] << std::endl;
return 0;
}
你可能會構建一個更簡單的測試案例更容易閱讀嗎?也許現在消除所有複雜的模板東西? –
添加了沒有所有模板的等效測試用例。 – tsuki
謝謝,這是更容易遵循! –