The article discusses techniques in C++ to enforce derived classes to implement a specific non-virtual method, using examples from C++/WRL and C++/WinRT, and critiques a code review scenario where comments were used instead of proper enforcement.
<p>You may have a base class that implements only partial functionality and relies on the derived class to do the rest. How do you make sure that the derived class does the rest?</p>
<p>For concreteness, let’s say that we are implementing <code>IValueConverter</code>, which has two methods:</p>
<ul>
<li><code>Convert()</code> to convert from the source to the destination.</li>
<li><code>ConvertBack()</code> so that two-way conversions can convert from the destination to the source.</li>
</ul>
<p>Suppose you want to write a base class called <code>OneWayConverter</code>. Its implementation fails the <code>ConvertBack()</code> call, and you want to force the derived class to implement the forward conversion.</p>
<pre>// C++/WRL
struct WidgetColorConverter :
Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>,
ABI::Windows::UI::Xaml::Data::IValueConverter>,
OneWayConverter
{
// Require the derived class to implement Convert somehow
HRESULT STDMETHODCALLTYPE Convert(IInspectable* value,
ABI::Windows::UI::Xaml::Interop::TypeName targetType,
IInspectable* parameter, HSTRING language,
IInspectable** result)
{
⟦ ... ⟧
}
};
// C++/WinRT
struct WidgetColorConverter :
winrt::implements<WidgetColorConverter>, OneWayConverter
{
// Require the derived class to implement Convert somehow
winrt::Windows::Foundation::IInspectable
Convert(
winrt::Windows::Foundation::IInspectable const& value,
winrt::Windows::UI::Xaml::Interop::TypeName const& targetType,
winrt::Windows::Foundation::IInspectable const& parameter,
winrt::hstring const& language)
{
⟦ ... ⟧
}
}
// Plain C++ analogous scenario
struct WidgetColorConverter : OneWayConverter
{
// Require the derived class to implement Convert somehow
Color Convert(Widget const&amp value)
{
⟦ ... ⟧
}
};
</pre>
<p>During a code review, I saw that somebody tried to do this just by writing a comment.</p>
<pre>// C++/WRL
struct OneWayConverter
{
// Derived classes must override this method.
HRESULT STDMETHODCALLTYPE Convert(IInspectable* /*value*/,
ABI::Windows::UI::Xaml::Interop::TypeName /*targetType*/,
IInspectable* /*parameter*/, HSTRING /*language*/,
IInspectable** result)
{
assert(false);
*result = nullptr;
return E_NOTIMPL;
}
// One-way converters cannot convert back
HRESULT STDMETHODCALLTYPE ConvertBack(IInspectable* /*value*/,
ABI::Windows::UI::Xaml::Interop::TypeName /*targetType*/,
IInspectable* /*parameter*/, HSTRING /*language*/,
IInspectable** result)
{
*result = nullptr;
return E_NOTIMPL;
}
};
// C++/WinRT
struct OneWayConverter
{
// Derived classes must override this method.
winrt::Windows::Foundation::IInspectable
Convert(
winrt::Windows::Foundation::IInspectable const& /*value*/,
winrt::Windows::UI::Xaml::Interop::TypeName const& /*targetType*/,
winrt::Windows::Foundation::IInspectable const& /*parameter*/,
winrt::hstring const& /*language*/)
{
assert(false);
throw winrt::hresult_not_implemented();
}
// One-way converters cannot convert back
winrt::Windows::Foundation::IInspectable
ConvertBack(
winrt::Windows::Foundation::IInspectable const& /*value*/,
winrt::Windows::UI::Xaml::Interop::TypeName const& /*targetType*/,
winrt::Windows::Foundation::IInspectable const& /*parameter*/,
winrt::hstring const& /*language*/)
{
throw winrt::hresult_not_implemented();
}
};
// Plain C++ analogous scenario
struct OneWayConverter
{
// Derived classes must override this method.
Color Convert(Widget const&amp /*value*/)
{
assert(false);
throw std::exception("not implemented");
}
// One-way converters cannot convert back
Widget ConvertBack(Color const& /*color*/)
{
throw std::exception("not implemented");
}
};
</pre>
<p>I pointed out that they were doing too much work.</p>
<p>The way to force somebody to implement a method in the derived class is simply not to implement the method in the base class in the first place.</p>
<pre>// C++/WRL
struct OneWayConverter
{
// Derived classes must implement Convert()
// One-way converters cannot convert back
HRESULT STDMETHODCALLTYPE ConvertBack(IInspectable* /*value*/,
ABI::Windows::UI::Xaml::Interop::TypeName /*targetType*/,
IInspectable* /*parameter*/, HSTRING /*language*/,
IInspectable** result)
{
*result = nullptr;
return E_NOTIMPL;
}
};
// C++/WinRT
struct OneWayConverter
{
// Derived classes must implement Convert()
// One-way converters cannot convert back
winrt::Windows::Foundation::IInspectable
ConvertBack(
winrt::Windows::Foundation::IInspectable const& /*value*/,
winrt::Windows::UI::Xaml::Interop::TypeName const& /*targetType*/,
winrt::Windows::Foundation::IInspectable const& /*parameter*/,
winrt::hstring const& /*language*/)
{
throw winrt::hresult_not_implemented();
}
};
// Plain C++ analogous scenario
struct OneWayConverter
{
// Derived classes must implement Convert()
// One-way converters cannot convert back
Widget ConvertBack(Color const& /*color*/)
{
throw std::exception("not implemented");
}
};
</pre>
<p>The error message if they forget to implement it depends on the library.</p>
<pre>// C++/WRL
struct WidgetColorConverter :
Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>,
OneWayConverter>
{
// Oops, forgot to implement Convert()
};
</pre>
<p>The error occurs when you call <code>WRL::<wbr />Make</code> to try to create the defective <code>WidgetColorConverter</code>.</p>
<pre style="white-space: pre-wrap;">wrl\implements.h(2512,32): error C2259: 'WidgetColorConverter': cannot instantiate abstract class
see declaration of 'WidgetColorConverter'
due to following members:
wrl\implements.h(2512,32):
'HRESULT ABI::<wbr />Windows::<wbr />UI::<wbr />Xaml::<wbr />Data::<wbr />IValueConverter::<wbr />Convert(IInspectable *,ABI::<wbr />Windows::<wbr />UI::<wbr />Xaml::<wbr />Interop::<wbr />TypeName,<wbr />IInspectable *,<wbr />HSTRING,<wbr />IInspectable **)': is abstract
windows.ui.xaml.data.h(2778,59):
see declaration of 'ABI::<wbr />Windows::<wbr />UI::<wbr />Xaml::<wbr />Data::<wbr />IValueConverter::<wbr />Convert'
wrl\implements.h(2512,32):
the template instantiation context (the oldest one first) is
test(41,30):
see reference to function template instantiation 'Microsoft::<wbr />WRL::<wbr />ComPtr<<wbr />WidgetColorConverter> Microsoft::<wbr />WRL::<wbr />Details::<wbr />Make<WidgetColorConverter,>(void)' being compiled
</pre>
<p>“Cannot instantiate abstract class due to the following members” is the standard error for failing to implement all the necessary pure virtual methods inherited from a base class, so one could expect that people who encounter this error will understand what it means.</p>
<pre>// C++/WinRT
struct WidgetColorConverter :
winrt::implements<WidgetColorConverter, winrt::Windows::UI::Xaml::Data::IValueConverter>,
OneWayConverter
{
// Oops, forgot to implement Convert()
};
</pre>
<p>The error occurs when you call <code>winrt::<wbr />make</code> to try to create the defective <code>WidgetColorConverter</code>.</p>
<pre style="white-space: pre-wrap;">windows.ui.xaml.data.h(1469,90): error C2039: 'Convert': is not a member of 'WidgetColorConverter'
test.cpp(66,8):
see declaration of 'WidgetColorConverter'
windows.ui.xaml.data.h(1469,90):
the template instantiation context (the oldest one first) is
test.cpp(66,31):
see reference to class template instantiation 'winrt::<wbr />implements<WidgetColorConverter,<wbr />winrt::<wbr />Windows::<wbr />UI::<wbr />Xaml::<wbr />Data::<wbr />IValueConverter>' being compiled
winrt\base.h(8088,31):
see reference to class template instantiation 'winrt::<wbr />impl::<wbr />producers_base<D,<wbr />std::tuple<<wbr />winrt::<wbr />Windows::<wbr />UI::<wbr />Xaml::<wbr />Data::<wbr />IValueConverter>>' being compiled
with
[
D=WidgetColorConverter
]
winrt\base.h(6763,50):
see reference to class template instantiation 'winrt::<wbr />impl::<wbr />producer_convert<D,<wbr />winrt::<wbr />Windows::<wbr />UI::<wbr />Xaml::<wbr />Data::<wbr />IValueConverter,<wbr />void>' being compiled
with
[
D=WidgetColorConverter
]
winrt\base.h(6734,31):
see reference to class template instantiation 'winrt::<wbr />impl::<wbr />producer<D,<wbr />winrt::<wbr />Windows::<wbr />UI::<wbr />Xaml::<wbr />Data::<wbr />IValueConverter,<wbr />void>' being compiled
with
[
D=WidgetColorConverter
]
winrt\base.h(7137,23):
see reference to class template instantiation 'winrt::<wbr />impl::<wbr />produce<D,I>' being compiled
with
[
D=WidgetColorConverter,
I=winrt::<wbr />Windows::<wbr />UI::<wbr />Xaml::<wbr />Data::<wbr />IValueConverter
]
winrt\windows.ui.xaml.data.h(1465,32):
while compiling class template member function 'int32_t winrt::<wbr />impl::<wbr />produce<D,I>::<wbr />Convert(<wbr />void *,<wbr />winrt::<wbr />impl::<wbr />struct_<wbr />Windows_<wbr />UI_<wbr />Xaml_<wbr />Interop_<wbr />TypeName,<wbr />void *,<wbr />void *,<wbr />void **) noexcept'
with
[
D=WidgetColorConverter,
I=winrt::<wbr />Windows::<wbr />UI::<wbr />Xaml::<wbr />Data::<wbr />IValueConverter
]
</pre>
<p>“⟦Name⟧ is not a member of” is typical of a CRTP error, since the template is trying to call a method on the derived class, but it’s not there. Again, one could expect that people who encounter this error will understand what it means.</p>
<p>For the plain C++ case, you might have this:</p>
<pre>// Plain C++ analogous scenario
struct WidgetColorConverter :
OneWayConverter
{
// Oops, forgot to implement Convert()
};
</pre>
<p>And everything works great until somebody tries to call the <code>Convert</code> method on a <code>WidgetColorConverter</code> and it’s not there.</p>
<pre style="white-space: pre-wrap;">test.cpp(79,20): error C2039: 'Convert': is not a member of 'WidgetColorConverter'
</pre>
<p>Again, this is a common error in C++ so you would hope that people understand what it means.</p>
<p>Great, so we were able to convert all of these authoring errors into compile-time errors, thereby avoiding the danger that somebody will use the base class and fail to implement all of the expected methods.</p>
<p>But wait, we can do better. We’ll look at this some more next time.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20260827-00/?p=112651">On forcing all derived classes to implement a specific non-virtual method, part 1</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
# On forcing all derived classes to implement a specific non-virtual method, part 1 - The Old New Thing
Source: [https://devblogs.microsoft.com/oldnewthing/20260827-00?p=112651](https://devblogs.microsoft.com/oldnewthing/20260827-00?p=112651)
You may have a base class that implements only partial functionality and relies on the derived class to do the rest\. How do you make sure that the derived class does the rest?
For concreteness, let’s say that we are implementing`IValueConverter`, which has two methods:
- `Convert\(\)`to convert from the source to the destination\.
- `ConvertBack\(\)`so that two\-way conversions can convert from the destination to the source\.
Suppose you want to write a base class called`OneWayConverter`\. Its implementation fails the`ConvertBack\(\)`call, and you want to force the derived class to implement the forward conversion\.
```
// C++/WRL
struct WidgetColorConverter :
Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>,
ABI::Windows::UI::Xaml::Data::IValueConverter>,
OneWayConverter
{
// Require the derived class to implement Convert somehow
HRESULT STDMETHODCALLTYPE Convert(IInspectable* value,
ABI::Windows::UI::Xaml::Interop::TypeName targetType,
IInspectable* parameter, HSTRING language,
IInspectable** result)
{
⟦ ... ⟧
}
};
// C++/WinRT
struct WidgetColorConverter :
winrt::implements<WidgetColorConverter>, OneWayConverter
{
// Require the derived class to implement Convert somehow
winrt::Windows::Foundation::IInspectable
Convert(
winrt::Windows::Foundation::IInspectable const& value,
winrt::Windows::UI::Xaml::Interop::TypeName const& targetType,
winrt::Windows::Foundation::IInspectable const& parameter,
winrt::hstring const& language)
{
⟦ ... ⟧
}
}
// Plain C++ analogous scenario
struct WidgetColorConverter : OneWayConverter
{
// Require the derived class to implement Convert somehow
Color Convert(Widget const& value)
{
⟦ ... ⟧
}
};
```
During a code review, I saw that somebody tried to do this just by writing a comment\.
```
// C++/WRL
struct OneWayConverter
{
// Derived classes must override this method.
HRESULT STDMETHODCALLTYPE Convert(IInspectable* /*value*/,
ABI::Windows::UI::Xaml::Interop::TypeName /*targetType*/,
IInspectable* /*parameter*/, HSTRING /*language*/,
IInspectable** result)
{
assert(false);
*result = nullptr;
return E_NOTIMPL;
}
// One-way converters cannot convert back
HRESULT STDMETHODCALLTYPE ConvertBack(IInspectable* /*value*/,
ABI::Windows::UI::Xaml::Interop::TypeName /*targetType*/,
IInspectable* /*parameter*/, HSTRING /*language*/,
IInspectable** result)
{
*result = nullptr;
return E_NOTIMPL;
}
};
// C++/WinRT
struct OneWayConverter
{
// Derived classes must override this method.
winrt::Windows::Foundation::IInspectable
Convert(
winrt::Windows::Foundation::IInspectable const& /*value*/,
winrt::Windows::UI::Xaml::Interop::TypeName const& /*targetType*/,
winrt::Windows::Foundation::IInspectable const& /*parameter*/,
winrt::hstring const& /*language*/)
{
assert(false);
throw winrt::hresult_not_implemented();
}
// One-way converters cannot convert back
winrt::Windows::Foundation::IInspectable
ConvertBack(
winrt::Windows::Foundation::IInspectable const& /*value*/,
winrt::Windows::UI::Xaml::Interop::TypeName const& /*targetType*/,
winrt::Windows::Foundation::IInspectable const& /*parameter*/,
winrt::hstring const& /*language*/)
{
throw winrt::hresult_not_implemented();
}
};
// Plain C++ analogous scenario
struct OneWayConverter
{
// Derived classes must override this method.
Color Convert(Widget const& /*value*/)
{
assert(false);
throw std::exception("not implemented");
}
// One-way converters cannot convert back
Widget ConvertBack(Color const& /*color*/)
{
throw std::exception("not implemented");
}
};
```
I pointed out that they were doing too much work\.
The way to force somebody to implement a method in the derived class is simply not to implement the method in the base class in the first place\.
```
// C++/WRL
struct OneWayConverter
{
// Derived classes must implement Convert()
// One-way converters cannot convert back
HRESULT STDMETHODCALLTYPE ConvertBack(IInspectable* /*value*/,
ABI::Windows::UI::Xaml::Interop::TypeName /*targetType*/,
IInspectable* /*parameter*/, HSTRING /*language*/,
IInspectable** result)
{
*result = nullptr;
return E_NOTIMPL;
}
};
// C++/WinRT
struct OneWayConverter
{
// Derived classes must implement Convert()
// One-way converters cannot convert back
winrt::Windows::Foundation::IInspectable
ConvertBack(
winrt::Windows::Foundation::IInspectable const& /*value*/,
winrt::Windows::UI::Xaml::Interop::TypeName const& /*targetType*/,
winrt::Windows::Foundation::IInspectable const& /*parameter*/,
winrt::hstring const& /*language*/)
{
throw winrt::hresult_not_implemented();
}
};
// Plain C++ analogous scenario
struct OneWayConverter
{
// Derived classes must implement Convert()
// One-way converters cannot convert back
Widget ConvertBack(Color const& /*color*/)
{
throw std::exception("not implemented");
}
};
```
The error message if they forget to implement it depends on the library\.
```
// C++/WRL
struct WidgetColorConverter :
Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRt>,
OneWayConverter>
{
// Oops, forgot to implement Convert()
};
```
The error occurs when you call`WRL::Make`to try to create the defective`WidgetColorConverter`\.
```
wrl\implements.h(2512,32): error C2259: 'WidgetColorConverter': cannot instantiate abstract class
see declaration of 'WidgetColorConverter'
due to following members:
wrl\implements.h(2512,32):
'HRESULT ABI::Windows::UI::Xaml::Data::IValueConverter::Convert(IInspectable *,ABI::Windows::UI::Xaml::Interop::TypeName,IInspectable *,HSTRING,IInspectable **)': is abstract
windows.ui.xaml.data.h(2778,59):
see declaration of 'ABI::Windows::UI::Xaml::Data::IValueConverter::Convert'
wrl\implements.h(2512,32):
the template instantiation context (the oldest one first) is
test(41,30):
see reference to function template instantiation 'Microsoft::WRL::ComPtr<WidgetColorConverter> Microsoft::WRL::Details::Make<WidgetColorConverter,>(void)' being compiled
```
“Cannot instantiate abstract class due to the following members” is the standard error for failing to implement all the necessary pure virtual methods inherited from a base class, so one could expect that people who encounter this error will understand what it means\.
```
// C++/WinRT
struct WidgetColorConverter :
winrt::implements<WidgetColorConverter, winrt::Windows::UI::Xaml::Data::IValueConverter>,
OneWayConverter
{
// Oops, forgot to implement Convert()
};
```
The error occurs when you call`winrt::make`to try to create the defective`WidgetColorConverter`\.
```
windows.ui.xaml.data.h(1469,90): error C2039: 'Convert': is not a member of 'WidgetColorConverter'
test.cpp(66,8):
see declaration of 'WidgetColorConverter'
windows.ui.xaml.data.h(1469,90):
the template instantiation context (the oldest one first) is
test.cpp(66,31):
see reference to class template instantiation 'winrt::implements<WidgetColorConverter,winrt::Windows::UI::Xaml::Data::IValueConverter>' being compiled
winrt\base.h(8088,31):
see reference to class template instantiation 'winrt::impl::producers_base<D,std::tuple<winrt::Windows::UI::Xaml::Data::IValueConverter>>' being compiled
with
[
D=WidgetColorConverter
]
winrt\base.h(6763,50):
see reference to class template instantiation 'winrt::impl::producer_convert<D,winrt::Windows::UI::Xaml::Data::IValueConverter,void>' being compiled
with
[
D=WidgetColorConverter
]
winrt\base.h(6734,31):
see reference to class template instantiation 'winrt::impl::producer<D,winrt::Windows::UI::Xaml::Data::IValueConverter,void>' being compiled
with
[
D=WidgetColorConverter
]
winrt\base.h(7137,23):
see reference to class template instantiation 'winrt::impl::produce<D,I>' being compiled
with
[
D=WidgetColorConverter,
I=winrt::Windows::UI::Xaml::Data::IValueConverter
]
winrt\windows.ui.xaml.data.h(1465,32):
while compiling class template member function 'int32_t winrt::impl::produce<D,I>::Convert(void *,winrt::impl::struct_Windows_UI_Xaml_Interop_TypeName,void *,void *,void **) noexcept'
with
[
D=WidgetColorConverter,
I=winrt::Windows::UI::Xaml::Data::IValueConverter
]
```
“⟦Name⟧ is not a member of” is typical of a CRTP error, since the template is trying to call a method on the derived class, but it’s not there\. Again, one could expect that people who encounter this error will understand what it means\.
For the plain C\+\+ case, you might have this:
```
// Plain C++ analogous scenario
struct WidgetColorConverter :
OneWayConverter
{
// Oops, forgot to implement Convert()
};
```
And everything works great until somebody tries to call the`Convert`method on a`WidgetColorConverter`and it’s not there\.
```
test.cpp(79,20): error C2039: 'Convert': is not a member of 'WidgetColorConverter'
```
Again, this is a common error in C\+\+ so you would hope that people understand what it means\.
Great, so we were able to convert all of these authoring errors into compile\-time errors, thereby avoiding the danger that somebody will use the base class and fail to implement all of the expected methods\.
But wait, we can do better\. We’ll look at this some more next time\.
### Category
### Topics
## Author

Raymond has been involved in the evolution of Windows for more than 30 years\. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie\-jeebies\. The Web site spawned a book, coincidentally also titled The Old New Thing \(Addison Wesley 2007\)\. He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information\.
The article explains how to use deleted functions in C++ to enforce derived class implementations of specific methods, improving compile-time error messages and developer guidance.
Raymond Chen continues his series on creating a fake agile wrapper in COM, explaining how to move non-marshalable objects by forwarding references into the force_marshal wrapper and discussing C++/WinRT deduction guides.
Raymond Chen continues his series on building an agile Windows Runtime delegate in C++/WinRT, comparing how C++/WinRT, C++/CX, and WRL handle non-marshalable delegates and agile reference creation.
The article discusses a fix for exception safety in C++/WinRT when creating an agile delegate, addressing the issue of unspecified lambda capture construction order to prevent reference leaks.
This blog post discusses handling Windows Runtime delegates that implement the INoMarshal interface in C++/WinRT, providing an agile delegate wrapper that checks the calling context to avoid marshaling errors.